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