View Javadoc

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