1 // ========================================================================
2 // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3 // ------------------------------------------------------------------------
4 // All rights reserved. This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v1.0
6 // and Apache License v2.0 which accompanies this distribution.
7 // The Eclipse Public License is available at
8 // http://www.eclipse.org/legal/epl-v10.html
9 // The Apache License v2.0 is available at
10 // http://www.opensource.org/licenses/apache2.0.php
11 // You may elect to redistribute this code under either of these licenses.
12 // ========================================================================
13
14 package org.eclipse.jetty.server.ssl;
15
16 import java.io.IOException;
17 import java.nio.channels.SocketChannel;
18
19 import javax.net.ssl.SSLContext;
20 import javax.net.ssl.SSLEngine;
21 import javax.net.ssl.SSLSession;
22 import javax.net.ssl.SSLSocket;
23
24 import org.eclipse.jetty.http.HttpSchemes;
25 import org.eclipse.jetty.io.AsyncEndPoint;
26 import org.eclipse.jetty.io.Buffers;
27 import org.eclipse.jetty.io.Buffers.Type;
28 import org.eclipse.jetty.io.BuffersFactory;
29 import org.eclipse.jetty.io.EndPoint;
30 import org.eclipse.jetty.io.RuntimeIOException;
31 import org.eclipse.jetty.io.bio.SocketEndPoint;
32 import org.eclipse.jetty.io.nio.AsyncConnection;
33 import org.eclipse.jetty.io.nio.SslConnection;
34 import org.eclipse.jetty.server.Request;
35 import org.eclipse.jetty.server.nio.SelectChannelConnector;
36 import org.eclipse.jetty.util.component.AggregateLifeCycle;
37 import org.eclipse.jetty.util.ssl.SslContextFactory;
38
39 /* ------------------------------------------------------------ */
40 /**
41 * SslSelectChannelConnector.
42 *
43 * @org.apache.xbean.XBean element="sslConnector" description="Creates an NIO ssl connector"
44 */
45 public class SslSelectChannelConnector extends SelectChannelConnector implements SslConnector
46 {
47 private final SslContextFactory _sslContextFactory;
48 private Buffers _sslBuffers;
49
50 /* ------------------------------------------------------------ */
51 public SslSelectChannelConnector()
52 {
53 this(new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH));
54 setSoLingerTime(30000);
55 }
56
57 /* ------------------------------------------------------------ */
58 /** Construct with explicit SslContextFactory.
59 * The SslContextFactory passed is added via {@link #addBean(Object)} so that
60 * it's lifecycle may be managed with {@link AggregateLifeCycle}.
61 * @param sslContextFactory
62 */
63 public SslSelectChannelConnector(SslContextFactory sslContextFactory)
64 {
65 _sslContextFactory = sslContextFactory;
66 addBean(_sslContextFactory);
67 setUseDirectBuffers(false);
68 setSoLingerTime(30000);
69 }
70
71 /* ------------------------------------------------------------ */
72 /**
73 * Allow the Listener a chance to customise the request. before the server
74 * does its stuff. <br>
75 * This allows the required attributes to be set for SSL requests. <br>
76 * The requirements of the Servlet specs are:
77 * <ul>
78 * <li> an attribute named "javax.servlet.request.ssl_session_id" of type
79 * String (since Servlet Spec 3.0).</li>
80 * <li> an attribute named "javax.servlet.request.cipher_suite" of type
81 * String.</li>
82 * <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li>
83 * <li> an attribute named "javax.servlet.request.X509Certificate" of type
84 * java.security.cert.X509Certificate[]. This is an array of objects of type
85 * X509Certificate, the order of this array is defined as being in ascending
86 * order of trust. The first certificate in the chain is the one set by the
87 * client, the next is the one used to authenticate the first, and so on.
88 * </li>
89 * </ul>
90 *
91 * @param endpoint
92 * The Socket the request arrived on. This should be a
93 * {@link SocketEndPoint} wrapping a {@link SSLSocket}.
94 * @param request
95 * HttpRequest to be customised.
96 */
97 @Override
98 public void customize(EndPoint endpoint, Request request) throws IOException
99 {
100 request.setScheme(HttpSchemes.HTTPS);
101 super.customize(endpoint,request);
102
103 SslConnection.SslEndPoint sslEndpoint=(SslConnection.SslEndPoint)endpoint;
104 SSLEngine sslEngine=sslEndpoint.getSslEngine();
105 SSLSession sslSession=sslEngine.getSession();
106
107 SslCertificates.customize(sslSession,endpoint,request);
108 }
109
110 /* ------------------------------------------------------------ */
111 /**
112 * @return True if SSL re-negotiation is allowed (default false)
113 * @deprecated
114 */
115 @Deprecated
116 public boolean isAllowRenegotiate()
117 {
118 return _sslContextFactory.isAllowRenegotiate();
119 }
120
121 /* ------------------------------------------------------------ */
122 /**
123 * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered
124 * a vulnerability in SSL/TLS with re-negotiation. If your JVM
125 * does not have CVE-2009-3555 fixed, then re-negotiation should
126 * not be allowed. CVE-2009-3555 was fixed in Sun java 1.6 with a ban
127 * of renegotiate in u19 and with RFC5746 in u22.
128 * @param allowRenegotiate true if re-negotiation is allowed (default false)
129 * @deprecated
130 */
131 @Deprecated
132 public void setAllowRenegotiate(boolean allowRenegotiate)
133 {
134 _sslContextFactory.setAllowRenegotiate(allowRenegotiate);
135 }
136
137 /* ------------------------------------------------------------ */
138 /**
139 * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites()
140 * @deprecated
141 */
142 @Deprecated
143 public String[] getExcludeCipherSuites()
144 {
145 return _sslContextFactory.getExcludeCipherSuites();
146 }
147
148 /* ------------------------------------------------------------ */
149 /**
150 * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[])
151 * @deprecated
152 */
153 @Deprecated
154 public void setExcludeCipherSuites(String[] cipherSuites)
155 {
156 _sslContextFactory.setExcludeCipherSuites(cipherSuites);
157 }
158
159 /* ------------------------------------------------------------ */
160 /**
161 * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites()
162 * @deprecated
163 */
164 @Deprecated
165 public String[] getIncludeCipherSuites()
166 {
167 return _sslContextFactory.getIncludeCipherSuites();
168 }
169
170 /* ------------------------------------------------------------ */
171 /**
172 * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[])
173 * @deprecated
174 */
175 @Deprecated
176 public void setIncludeCipherSuites(String[] cipherSuites)
177 {
178 _sslContextFactory.setIncludeCipherSuites(cipherSuites);
179 }
180
181 /* ------------------------------------------------------------ */
182 /**
183 * @see org.eclipse.jetty.server.ssl.SslConnector#setPassword(java.lang.String)
184 * @deprecated
185 */
186 @Deprecated
187 public void setPassword(String password)
188 {
189 _sslContextFactory.setKeyStorePassword(password);
190 }
191
192 /* ------------------------------------------------------------ */
193 /**
194 * @see org.eclipse.jetty.server.ssl.SslConnector#setTrustPassword(java.lang.String)
195 * @deprecated
196 */
197 @Deprecated
198 public void setTrustPassword(String password)
199 {
200 _sslContextFactory.setTrustStorePassword(password);
201 }
202
203 /* ------------------------------------------------------------ */
204 /**
205 * @see org.eclipse.jetty.server.ssl.SslConnector#setKeyPassword(java.lang.String)
206 * @deprecated
207 */
208 @Deprecated
209 public void setKeyPassword(String password)
210 {
211 _sslContextFactory.setKeyManagerPassword(password);
212 }
213
214 /* ------------------------------------------------------------ */
215 /**
216 * Unsupported.
217 *
218 * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past)
219 * @deprecated
220 */
221 @Deprecated
222 public String getAlgorithm()
223 {
224 throw new UnsupportedOperationException();
225 }
226
227 /* ------------------------------------------------------------ */
228 /**
229 * Unsupported.
230 *
231 * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past)
232 * @deprecated
233 */
234 @Deprecated
235 public void setAlgorithm(String algorithm)
236 {
237 throw new UnsupportedOperationException();
238 }
239
240 /* ------------------------------------------------------------ */
241 /**
242 * @see org.eclipse.jetty.server.ssl.SslConnector#getProtocol()
243 * @deprecated
244 */
245 @Deprecated
246 public String getProtocol()
247 {
248 return _sslContextFactory.getProtocol();
249 }
250
251 /* ------------------------------------------------------------ */
252 /**
253 * @see org.eclipse.jetty.server.ssl.SslConnector#setProtocol(java.lang.String)
254 * @deprecated
255 */
256 @Deprecated
257 public void setProtocol(String protocol)
258 {
259 _sslContextFactory.setProtocol(protocol);
260 }
261
262 /* ------------------------------------------------------------ */
263 /**
264 * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystore(java.lang.String)
265 * @deprecated
266 */
267 @Deprecated
268 public void setKeystore(String keystore)
269 {
270 _sslContextFactory.setKeyStorePath(keystore);
271 }
272
273 /* ------------------------------------------------------------ */
274 /**
275 * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystore()
276 * @deprecated
277 */
278 @Deprecated
279 public String getKeystore()
280 {
281 return _sslContextFactory.getKeyStorePath();
282 }
283
284 /* ------------------------------------------------------------ */
285 /**
286 * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystoreType()
287 * @deprecated
288 */
289 @Deprecated
290 public String getKeystoreType()
291 {
292 return _sslContextFactory.getKeyStoreType();
293 }
294
295 /* ------------------------------------------------------------ */
296 /**
297 * @see org.eclipse.jetty.server.ssl.SslConnector#getNeedClientAuth()
298 * @deprecated
299 */
300 @Deprecated
301 public boolean getNeedClientAuth()
302 {
303 return _sslContextFactory.getNeedClientAuth();
304 }
305
306 /* ------------------------------------------------------------ */
307 /**
308 * @see org.eclipse.jetty.server.ssl.SslConnector#getWantClientAuth()
309 * @deprecated
310 */
311 @Deprecated
312 public boolean getWantClientAuth()
313 {
314 return _sslContextFactory.getWantClientAuth();
315 }
316
317 /* ------------------------------------------------------------ */
318 /**
319 * @see org.eclipse.jetty.server.ssl.SslConnector#setNeedClientAuth(boolean)
320 * @deprecated
321 */
322 @Deprecated
323 public void setNeedClientAuth(boolean needClientAuth)
324 {
325 _sslContextFactory.setNeedClientAuth(needClientAuth);
326 }
327
328 /* ------------------------------------------------------------ */
329 /**
330 * @see org.eclipse.jetty.server.ssl.SslConnector#setWantClientAuth(boolean)
331 * @deprecated
332 */
333 @Deprecated
334 public void setWantClientAuth(boolean wantClientAuth)
335 {
336 _sslContextFactory.setWantClientAuth(wantClientAuth);
337 }
338
339 /* ------------------------------------------------------------ */
340 /**
341 * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystoreType(java.lang.String)
342 * @deprecated
343 */
344 @Deprecated
345 public void setKeystoreType(String keystoreType)
346 {
347 _sslContextFactory.setKeyStoreType(keystoreType);
348 }
349
350 /* ------------------------------------------------------------ */
351 /**
352 * @see org.eclipse.jetty.server.ssl.SslConnector#getProvider()
353 * @deprecated
354 */
355 @Deprecated
356 public String getProvider()
357 {
358 return _sslContextFactory.getProvider();
359 }
360
361 /* ------------------------------------------------------------ */
362 /**
363 * @see org.eclipse.jetty.server.ssl.SslConnector#getSecureRandomAlgorithm()
364 * @deprecated
365 */
366 @Deprecated
367 public String getSecureRandomAlgorithm()
368 {
369 return _sslContextFactory.getSecureRandomAlgorithm();
370 }
371
372 /* ------------------------------------------------------------ */
373 /**
374 * @see org.eclipse.jetty.server.ssl.SslConnector#getSslKeyManagerFactoryAlgorithm()
375 * @deprecated
376 */
377 @Deprecated
378 public String getSslKeyManagerFactoryAlgorithm()
379 {
380 return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
381 }
382
383 /* ------------------------------------------------------------ */
384 /**
385 * @see org.eclipse.jetty.server.ssl.SslConnector#getSslTrustManagerFactoryAlgorithm()
386 * @deprecated
387 */
388 @Deprecated
389 public String getSslTrustManagerFactoryAlgorithm()
390 {
391 return _sslContextFactory.getTrustManagerFactoryAlgorithm();
392 }
393
394 /* ------------------------------------------------------------ */
395 /**
396 * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststore()
397 * @deprecated
398 */
399 @Deprecated
400 public String getTruststore()
401 {
402 return _sslContextFactory.getTrustStore();
403 }
404
405 /* ------------------------------------------------------------ */
406 /**
407 * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststoreType()
408 * @deprecated
409 */
410 @Deprecated
411 public String getTruststoreType()
412 {
413 return _sslContextFactory.getTrustStoreType();
414 }
415
416 /* ------------------------------------------------------------ */
417 /**
418 * @see org.eclipse.jetty.server.ssl.SslConnector#setProvider(java.lang.String)
419 * @deprecated
420 */
421 @Deprecated
422 public void setProvider(String provider)
423 {
424 _sslContextFactory.setProvider(provider);
425 }
426
427 /* ------------------------------------------------------------ */
428 /**
429 * @see org.eclipse.jetty.server.ssl.SslConnector#setSecureRandomAlgorithm(java.lang.String)
430 * @deprecated
431 */
432 @Deprecated
433 public void setSecureRandomAlgorithm(String algorithm)
434 {
435 _sslContextFactory.setSecureRandomAlgorithm(algorithm);
436 }
437
438 /* ------------------------------------------------------------ */
439 /**
440 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslKeyManagerFactoryAlgorithm(java.lang.String)
441 * @deprecated
442 */
443 @Deprecated
444 public void setSslKeyManagerFactoryAlgorithm(String algorithm)
445 {
446 _sslContextFactory.setSslKeyManagerFactoryAlgorithm(algorithm);
447 }
448
449 /* ------------------------------------------------------------ */
450 /**
451 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslTrustManagerFactoryAlgorithm(java.lang.String)
452 * @deprecated
453 */
454 @Deprecated
455 public void setSslTrustManagerFactoryAlgorithm(String algorithm)
456 {
457 _sslContextFactory.setTrustManagerFactoryAlgorithm(algorithm);
458 }
459
460 /* ------------------------------------------------------------ */
461 /**
462 * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststore(java.lang.String)
463 * @deprecated
464 */
465 @Deprecated
466 public void setTruststore(String truststore)
467 {
468 _sslContextFactory.setTrustStore(truststore);
469 }
470
471 /* ------------------------------------------------------------ */
472 /**
473 * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststoreType(java.lang.String)
474 * @deprecated
475 */
476 @Deprecated
477 public void setTruststoreType(String truststoreType)
478 {
479 _sslContextFactory.setTrustStoreType(truststoreType);
480 }
481
482 /* ------------------------------------------------------------ */
483 /**
484 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext)
485 * @deprecated
486 */
487 @Deprecated
488 public void setSslContext(SSLContext sslContext)
489 {
490 _sslContextFactory.setSslContext(sslContext);
491 }
492
493 /* ------------------------------------------------------------ */
494 /**
495 * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext)
496 * @deprecated
497 */
498 @Deprecated
499 public SSLContext getSslContext()
500 {
501 return _sslContextFactory.getSslContext();
502 }
503
504 /* ------------------------------------------------------------ */
505 /**
506 * @see org.eclipse.jetty.server.ssl.SslConnector#getSslContextFactory()
507 */
508 public SslContextFactory getSslContextFactory()
509 {
510 return _sslContextFactory;
511 }
512
513 /* ------------------------------------------------------------ */
514 /**
515 * By default, we're confidential, given we speak SSL. But, if we've been
516 * told about an confidential port, and said port is not our port, then
517 * we're not. This allows separation of listeners providing INTEGRAL versus
518 * CONFIDENTIAL constraints, such as one SSL listener configured to require
519 * client certs providing CONFIDENTIAL, whereas another SSL listener not
520 * requiring client certs providing mere INTEGRAL constraints.
521 */
522 @Override
523 public boolean isConfidential(Request request)
524 {
525 final int confidentialPort=getConfidentialPort();
526 return confidentialPort==0||confidentialPort==request.getServerPort();
527 }
528
529 /* ------------------------------------------------------------ */
530 /**
531 * By default, we're integral, given we speak SSL. But, if we've been told
532 * about an integral port, and said port is not our port, then we're not.
533 * This allows separation of listeners providing INTEGRAL versus
534 * CONFIDENTIAL constraints, such as one SSL listener configured to require
535 * client certs providing CONFIDENTIAL, whereas another SSL listener not
536 * requiring client certs providing mere INTEGRAL constraints.
537 */
538 @Override
539 public boolean isIntegral(Request request)
540 {
541 final int integralPort=getIntegralPort();
542 return integralPort==0||integralPort==request.getServerPort();
543 }
544
545 /* ------------------------------------------------------------------------------- */
546 @Override
547 protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint)
548 {
549 try
550 {
551 SSLEngine engine = createSSLEngine(channel);
552 SslConnection connection = newSslConnection(endpoint, engine);
553 AsyncConnection delegate = newPlainConnection(channel, connection.getSslEndPoint());
554 connection.getSslEndPoint().setConnection(delegate);
555 connection.setAllowRenegotiate(_sslContextFactory.isAllowRenegotiate());
556 return connection;
557 }
558 catch (IOException e)
559 {
560 throw new RuntimeIOException(e);
561 }
562 }
563
564 protected AsyncConnection newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint)
565 {
566 return super.newConnection(channel, endPoint);
567 }
568
569 protected SslConnection newSslConnection(AsyncEndPoint endpoint, SSLEngine engine)
570 {
571 return new SslConnection(engine, endpoint);
572 }
573
574 /* ------------------------------------------------------------ */
575 /**
576 * @param channel A channel which if passed is used as to extract remote
577 * host and port for the purposes of SSL session caching
578 * @return A SSLEngine for a new or cached SSL Session
579 * @throws IOException if the SSLEngine cannot be created
580 */
581 protected SSLEngine createSSLEngine(SocketChannel channel) throws IOException
582 {
583 SSLEngine engine;
584 if (channel != null)
585 {
586 String peerHost = channel.socket().getInetAddress().getHostAddress();
587 int peerPort = channel.socket().getPort();
588 engine = _sslContextFactory.newSslEngine(peerHost, peerPort);
589 }
590 else
591 {
592 engine = _sslContextFactory.newSslEngine();
593 }
594
595 engine.setUseClientMode(false);
596 return engine;
597 }
598
599 /* ------------------------------------------------------------ */
600 /**
601 * @see org.eclipse.jetty.server.nio.SelectChannelConnector#doStart()
602 */
603 @Override
604 protected void doStart() throws Exception
605 {
606 _sslContextFactory.checkKeyStore();
607 _sslContextFactory.start();
608
609 SSLEngine sslEngine = _sslContextFactory.newSslEngine();
610
611 sslEngine.setUseClientMode(false);
612
613 SSLSession sslSession = sslEngine.getSession();
614
615 _sslBuffers = BuffersFactory.newBuffers(
616 getUseDirectBuffers()?Type.DIRECT:Type.INDIRECT,sslSession.getApplicationBufferSize(),
617 getUseDirectBuffers()?Type.DIRECT:Type.INDIRECT,sslSession.getApplicationBufferSize(),
618 getUseDirectBuffers()?Type.DIRECT:Type.INDIRECT,getMaxBuffers()
619 );
620
621 if (getRequestHeaderSize()<sslSession.getApplicationBufferSize())
622 setRequestHeaderSize(sslSession.getApplicationBufferSize());
623 if (getRequestBufferSize()<sslSession.getApplicationBufferSize())
624 setRequestBufferSize(sslSession.getApplicationBufferSize());
625
626 super.doStart();
627 }
628
629 /* ------------------------------------------------------------ */
630 /**
631 * @see org.eclipse.jetty.server.nio.SelectChannelConnector#doStop()
632 */
633 @Override
634 protected void doStop() throws Exception
635 {
636 _sslBuffers=null;
637 super.doStop();
638 }
639
640 /* ------------------------------------------------------------ */
641 /**
642 * @return SSL buffers
643 */
644 public Buffers getSslBuffers()
645 {
646 return _sslBuffers;
647 }
648 }