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