View Javadoc

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 }