1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2014 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.net.ServerSocket;
23 import java.net.Socket;
24 
25 import javax.net.ssl.HandshakeCompletedEvent;
26 import javax.net.ssl.HandshakeCompletedListener;
27 import javax.net.ssl.SSLContext;
28 import javax.net.ssl.SSLException;
29 import javax.net.ssl.SSLServerSocket;
30 import javax.net.ssl.SSLSession;
31 import javax.net.ssl.SSLSocket;
32 
33 import org.eclipse.jetty.http.HttpSchemes;
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.server.Request;
38 import org.eclipse.jetty.server.bio.SocketConnector;
39 import org.eclipse.jetty.util.log.Log;
40 import org.eclipse.jetty.util.log.Logger;
41 import org.eclipse.jetty.util.ssl.SslContextFactory;
42 
43 /* ------------------------------------------------------------ */
44 /**
45  * SSL Socket Connector.
46  *
47  * This specialization of SocketConnector is an abstract listener that can be used as the basis for a
48  * specific JSSE listener.
49  *
50  * The original of this class was heavily based on the work from Court Demas, which in turn is
51  * based on the work from Forge Research. Since JSSE, this class has evolved significantly from
52  * that early work.
53  *
54  * @org.apache.xbean.XBean element="sslSocketConnector" description="Creates an ssl socket connector"
55  *
56  *
57  */
58 public class SslSocketConnector extends SocketConnector  implements SslConnector
59 {
60     private static final Logger LOG = Log.getLogger(SslSocketConnector.class);
61 
62     private final SslContextFactory _sslContextFactory;
63     private int _handshakeTimeout = 0; //0 means use maxIdleTime
64 
65     /* ------------------------------------------------------------ */
66     /**
67      * Constructor.
68      */
SslSocketConnector()69     public SslSocketConnector()
70     {
71         this(new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH));
72         setSoLingerTime(30000);
73     }
74 
75     /* ------------------------------------------------------------ */
SslSocketConnector(SslContextFactory sslContextFactory)76     public SslSocketConnector(SslContextFactory sslContextFactory)
77     {
78         _sslContextFactory = sslContextFactory;
79     }
80 
81     /* ------------------------------------------------------------ */
82     /**
83      * @return True if SSL re-negotiation is allowed (default false)
84      */
isAllowRenegotiate()85     public boolean isAllowRenegotiate()
86     {
87         return _sslContextFactory.isAllowRenegotiate();
88     }
89 
90     /* ------------------------------------------------------------ */
91     /**
92      * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered
93      * a vulnerability in SSL/TLS with re-negotiation.  If your JVM
94      * does not have CVE-2009-3555 fixed, then re-negotiation should
95      * not be allowed.
96      * @param allowRenegotiate true if re-negotiation is allowed (default false)
97      */
setAllowRenegotiate(boolean allowRenegotiate)98     public void setAllowRenegotiate(boolean allowRenegotiate)
99     {
100         _sslContextFactory.setAllowRenegotiate(allowRenegotiate);
101     }
102 
103     /* ------------------------------------------------------------ */
104     @Override
accept(int acceptorID)105     public void accept(int acceptorID)
106         throws IOException, InterruptedException
107     {
108         Socket socket = _serverSocket.accept();
109         configure(socket);
110 
111         ConnectorEndPoint connection=new SslConnectorEndPoint(socket);
112         connection.dispatch();
113     }
114 
115     /* ------------------------------------------------------------ */
116     @Override
configure(Socket socket)117     protected void configure(Socket socket)
118         throws IOException
119     {
120         super.configure(socket);
121     }
122 
123     /* ------------------------------------------------------------ */
124     /**
125      * Allow the Listener a chance to customise the request. before the server does its stuff. <br>
126      * This allows the required attributes to be set for SSL requests. <br>
127      * The requirements of the Servlet specs are:
128      * <ul>
129      * <li> an attribute named "javax.servlet.request.ssl_id" of type String (since Spec 3.0).</li>
130      * <li> an attribute named "javax.servlet.request.cipher_suite" of type String.</li>
131      * <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li>
132      * <li> an attribute named "javax.servlet.request.X509Certificate" of type
133      * java.security.cert.X509Certificate[]. This is an array of objects of type X509Certificate,
134      * the order of this array is defined as being in ascending order of trust. The first
135      * certificate in the chain is the one set by the client, the next is the one used to
136      * authenticate the first, and so on. </li>
137      * </ul>
138      *
139      * @param endpoint The Socket the request arrived on.
140      *        This should be a {@link SocketEndPoint} wrapping a {@link SSLSocket}.
141      * @param request HttpRequest to be customised.
142      */
143     @Override
customize(EndPoint endpoint, Request request)144     public void customize(EndPoint endpoint, Request request)
145         throws IOException
146     {
147         super.customize(endpoint, request);
148         request.setScheme(HttpSchemes.HTTPS);
149 
150         SocketEndPoint socket_end_point = (SocketEndPoint)endpoint;
151         SSLSocket sslSocket = (SSLSocket)socket_end_point.getTransport();
152         SSLSession sslSession = sslSocket.getSession();
153 
154         SslCertificates.customize(sslSession,endpoint,request);
155     }
156 
157     /* ------------------------------------------------------------ */
158     /**
159      * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites()
160      * @deprecated
161      */
162     @Deprecated
getExcludeCipherSuites()163     public String[] getExcludeCipherSuites() {
164         return _sslContextFactory.getExcludeCipherSuites();
165     }
166 
167     /* ------------------------------------------------------------ */
168     /**
169      * @see org.eclipse.jetty.server.ssl.SslConnector#getIncludeCipherSuites()
170      * @deprecated
171      */
172     @Deprecated
getIncludeCipherSuites()173     public String[] getIncludeCipherSuites()
174     {
175         return _sslContextFactory.getIncludeCipherSuites();
176     }
177 
178     /* ------------------------------------------------------------ */
179     /**
180      * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystore()
181      * @deprecated
182      */
183     @Deprecated
getKeystore()184     public String getKeystore()
185     {
186         return _sslContextFactory.getKeyStorePath();
187     }
188 
189     /* ------------------------------------------------------------ */
190     /**
191      * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystoreType()
192      * @deprecated
193      */
194     @Deprecated
getKeystoreType()195     public String getKeystoreType()
196     {
197         return _sslContextFactory.getKeyStoreType();
198     }
199 
200     /* ------------------------------------------------------------ */
201     /**
202      * @see org.eclipse.jetty.server.ssl.SslConnector#getNeedClientAuth()
203      * @deprecated
204      */
205     @Deprecated
getNeedClientAuth()206     public boolean getNeedClientAuth()
207     {
208         return _sslContextFactory.getNeedClientAuth();
209     }
210 
211     /* ------------------------------------------------------------ */
212     /**
213      * @see org.eclipse.jetty.server.ssl.SslConnector#getProtocol()
214      * @deprecated
215      */
216     @Deprecated
getProtocol()217     public String getProtocol()
218     {
219         return _sslContextFactory.getProtocol();
220     }
221 
222     /* ------------------------------------------------------------ */
223     /**
224      * @see org.eclipse.jetty.server.ssl.SslConnector#getProvider()
225      * @deprecated
226      */
227     @Deprecated
getProvider()228     public String getProvider() {
229 	return _sslContextFactory.getProvider();
230     }
231 
232     /* ------------------------------------------------------------ */
233     /**
234      * @see org.eclipse.jetty.server.ssl.SslConnector#getSecureRandomAlgorithm()
235      * @deprecated
236      */
237     @Deprecated
getSecureRandomAlgorithm()238     public String getSecureRandomAlgorithm()
239     {
240         return _sslContextFactory.getSecureRandomAlgorithm();
241     }
242 
243     /* ------------------------------------------------------------ */
244     /**
245      * @see org.eclipse.jetty.server.ssl.SslConnector#getSslKeyManagerFactoryAlgorithm()
246      * @deprecated
247      */
248     @Deprecated
getSslKeyManagerFactoryAlgorithm()249     public String getSslKeyManagerFactoryAlgorithm()
250     {
251         return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
252     }
253 
254     /* ------------------------------------------------------------ */
255     /**
256      * @see org.eclipse.jetty.server.ssl.SslConnector#getSslTrustManagerFactoryAlgorithm()
257      * @deprecated
258      */
259     @Deprecated
getSslTrustManagerFactoryAlgorithm()260     public String getSslTrustManagerFactoryAlgorithm()
261     {
262         return _sslContextFactory.getTrustManagerFactoryAlgorithm();
263     }
264 
265     /* ------------------------------------------------------------ */
266     /**
267      * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststore()
268      * @deprecated
269      */
270     @Deprecated
getTruststore()271     public String getTruststore()
272     {
273         return _sslContextFactory.getTrustStore();
274     }
275 
276     /* ------------------------------------------------------------ */
277     /**
278      * @see org.eclipse.jetty.server.ssl.SslConnector#getSslContextFactory()
279      */
280 //    @Override
getSslContextFactory()281     public SslContextFactory getSslContextFactory()
282     {
283         return _sslContextFactory;
284     }
285 
286     /* ------------------------------------------------------------ */
287     /**
288      * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststoreType()
289      * @deprecated
290      */
291     @Deprecated
getTruststoreType()292     public String getTruststoreType()
293     {
294         return _sslContextFactory.getTrustStoreType();
295     }
296 
297     /* ------------------------------------------------------------ */
298     /**
299      * @see org.eclipse.jetty.server.ssl.SslConnector#getWantClientAuth()
300      * @deprecated
301      */
302     @Deprecated
getWantClientAuth()303     public boolean getWantClientAuth()
304     {
305         return _sslContextFactory.getWantClientAuth();
306     }
307 
308     /* ------------------------------------------------------------ */
309     /**
310      * By default, we're confidential, given we speak SSL. But, if we've been told about an
311      * confidential port, and said port is not our port, then we're not. This allows separation of
312      * listeners providing INTEGRAL versus CONFIDENTIAL constraints, such as one SSL listener
313      * configured to require client certs providing CONFIDENTIAL, whereas another SSL listener not
314      * requiring client certs providing mere INTEGRAL constraints.
315      */
316     @Override
isConfidential(Request request)317     public boolean isConfidential(Request request)
318     {
319         final int confidentialPort = getConfidentialPort();
320         return confidentialPort == 0 || confidentialPort == request.getServerPort();
321     }
322 
323     /* ------------------------------------------------------------ */
324     /**
325      * By default, we're integral, given we speak SSL. But, if we've been told about an integral
326      * port, and said port is not our port, then we're not. This allows separation of listeners
327      * providing INTEGRAL versus CONFIDENTIAL constraints, such as one SSL listener configured to
328      * require client certs providing CONFIDENTIAL, whereas another SSL listener not requiring
329      * client certs providing mere INTEGRAL constraints.
330      */
331     @Override
isIntegral(Request request)332     public boolean isIntegral(Request request)
333     {
334         final int integralPort = getIntegralPort();
335         return integralPort == 0 || integralPort == request.getServerPort();
336     }
337 
338     /* ------------------------------------------------------------ */
339     @Override
open()340     public void open() throws IOException
341     {
342         _sslContextFactory.checkKeyStore();
343         try
344         {
345             _sslContextFactory.start();
346         }
347         catch(Exception e)
348         {
349             throw new RuntimeIOException(e);
350         }
351         super.open();
352     }
353 
354     /* ------------------------------------------------------------ */
355     /**
356      * {@inheritDoc}
357      */
358     @Override
doStart()359     protected void doStart() throws Exception
360     {
361         _sslContextFactory.checkKeyStore();
362         _sslContextFactory.start();
363 
364         super.doStart();
365     }
366 
367     /* ------------------------------------------------------------ */
368     /**
369      * @see org.eclipse.jetty.server.bio.SocketConnector#doStop()
370      */
371     @Override
doStop()372     protected void doStop() throws Exception
373     {
374         _sslContextFactory.stop();
375 
376         super.doStop();
377     }
378 
379     /* ------------------------------------------------------------ */
380     /**
381      * @param host The host name that this server should listen on
382      * @param port the port that this server should listen on
383      * @param backlog See {@link ServerSocket#bind(java.net.SocketAddress, int)}
384      * @return A new {@link ServerSocket socket object} bound to the supplied address with all other
385      * settings as per the current configuration of this connector.
386      * @see #setWantClientAuth(boolean)
387      * @see #setNeedClientAuth(boolean)
388      * @exception IOException
389      */
390     @Override
newServerSocket(String host, int port,int backlog)391     protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException
392     {
393        return _sslContextFactory.newSslServerSocket(host,port,backlog);
394     }
395 
396     /* ------------------------------------------------------------ */
397     /**
398      * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[])
399      * @deprecated
400      */
401     @Deprecated
setExcludeCipherSuites(String[] cipherSuites)402     public void setExcludeCipherSuites(String[] cipherSuites)
403     {
404         _sslContextFactory.setExcludeCipherSuites(cipherSuites);
405     }
406 
407     /* ------------------------------------------------------------ */
408     /**
409      * @see org.eclipse.jetty.server.ssl.SslConnector#setIncludeCipherSuites(java.lang.String[])
410      * @deprecated
411      */
412     @Deprecated
setIncludeCipherSuites(String[] cipherSuites)413     public void setIncludeCipherSuites(String[] cipherSuites)
414     {
415         _sslContextFactory.setIncludeCipherSuites(cipherSuites);
416     }
417 
418     /* ------------------------------------------------------------ */
419     /**
420      * @see org.eclipse.jetty.server.ssl.SslConnector#setKeyPassword(java.lang.String)
421      * @deprecated
422      */
423     @Deprecated
setKeyPassword(String password)424     public void setKeyPassword(String password)
425     {
426         _sslContextFactory.setKeyManagerPassword(password);
427     }
428 
429     /* ------------------------------------------------------------ */
430     /**
431      * @param keystore The resource path to the keystore, or null for built in keystores.
432      * @deprecated
433      */
434     @Deprecated
setKeystore(String keystore)435     public void setKeystore(String keystore)
436     {
437         _sslContextFactory.setKeyStorePath(keystore);
438     }
439 
440     /* ------------------------------------------------------------ */
441     /**
442      * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystoreType(java.lang.String)
443      * @deprecated
444      */
445     @Deprecated
setKeystoreType(String keystoreType)446     public void setKeystoreType(String keystoreType)
447     {
448         _sslContextFactory.setKeyStoreType(keystoreType);
449     }
450 
451     /* ------------------------------------------------------------ */
452     /**
453      * Set the value of the needClientAuth property
454      *
455      * @param needClientAuth true iff we require client certificate authentication.
456      * @deprecated
457      */
458     @Deprecated
setNeedClientAuth(boolean needClientAuth)459     public void setNeedClientAuth(boolean needClientAuth)
460     {
461         _sslContextFactory.setNeedClientAuth(needClientAuth);
462     }
463 
464     /* ------------------------------------------------------------ */
465     /**
466      * @see org.eclipse.jetty.server.ssl.SslConnector#setPassword(java.lang.String)
467      * @deprecated
468      */
469     @Deprecated
setPassword(String password)470     public void setPassword(String password)
471     {
472         _sslContextFactory.setKeyStorePassword(password);
473     }
474 
475     /* ------------------------------------------------------------ */
476     /**
477      * @see org.eclipse.jetty.server.ssl.SslConnector#setTrustPassword(java.lang.String)
478      * @deprecated
479      */
480     @Deprecated
setTrustPassword(String password)481     public void setTrustPassword(String password)
482     {
483         _sslContextFactory.setTrustStorePassword(password);
484     }
485 
486     /* ------------------------------------------------------------ */
487     /**
488      * @see org.eclipse.jetty.server.ssl.SslConnector#setProtocol(java.lang.String)
489      * @deprecated
490      */
491     @Deprecated
setProtocol(String protocol)492     public void setProtocol(String protocol)
493     {
494         _sslContextFactory.setProtocol(protocol);
495     }
496 
497     /* ------------------------------------------------------------ */
498     /**
499      * @see org.eclipse.jetty.server.ssl.SslConnector#setProvider(java.lang.String)
500      * @deprecated
501      */
502     @Deprecated
setProvider(String provider)503     public void setProvider(String provider) {
504         _sslContextFactory.setProvider(provider);
505     }
506 
507     /* ------------------------------------------------------------ */
508     /**
509      * @see org.eclipse.jetty.server.ssl.SslConnector#setSecureRandomAlgorithm(java.lang.String)
510      * @deprecated
511      */
512     @Deprecated
setSecureRandomAlgorithm(String algorithm)513     public void setSecureRandomAlgorithm(String algorithm)
514     {
515         _sslContextFactory.setSecureRandomAlgorithm(algorithm);
516     }
517 
518     /* ------------------------------------------------------------ */
519     /**
520      * @see org.eclipse.jetty.server.ssl.SslConnector#setSslKeyManagerFactoryAlgorithm(java.lang.String)
521      * @deprecated
522      */
523     @Deprecated
setSslKeyManagerFactoryAlgorithm(String algorithm)524     public void setSslKeyManagerFactoryAlgorithm(String algorithm)
525     {
526         _sslContextFactory.setSslKeyManagerFactoryAlgorithm(algorithm);
527     }
528 
529     /* ------------------------------------------------------------ */
530     /**
531      * @see org.eclipse.jetty.server.ssl.SslConnector#setSslTrustManagerFactoryAlgorithm(java.lang.String)
532      * @deprecated
533      */
534     @Deprecated
setSslTrustManagerFactoryAlgorithm(String algorithm)535     public void setSslTrustManagerFactoryAlgorithm(String algorithm)
536     {
537         _sslContextFactory.setTrustManagerFactoryAlgorithm(algorithm);
538     }
539 
540     /* ------------------------------------------------------------ */
541     /**
542      * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststore(java.lang.String)
543      * @deprecated
544      */
545     @Deprecated
setTruststore(String truststore)546     public void setTruststore(String truststore)
547     {
548         _sslContextFactory.setTrustStore(truststore);
549     }
550 
551     /* ------------------------------------------------------------ */
552     /**
553      * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststoreType(java.lang.String)
554      * @deprecated
555      */
556     @Deprecated
setTruststoreType(String truststoreType)557     public void setTruststoreType(String truststoreType)
558     {
559         _sslContextFactory.setTrustStoreType(truststoreType);
560     }
561 
562     /* ------------------------------------------------------------ */
563     /**
564      * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext)
565      * @deprecated
566      */
567     @Deprecated
setSslContext(SSLContext sslContext)568     public void setSslContext(SSLContext sslContext)
569     {
570         _sslContextFactory.setSslContext(sslContext);
571     }
572 
573     /* ------------------------------------------------------------ */
574     /**
575      * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext)
576      * @deprecated
577      */
578     @Deprecated
getSslContext()579     public SSLContext getSslContext()
580     {
581         return _sslContextFactory.getSslContext();
582     }
583 
584     /* ------------------------------------------------------------ */
585     /**
586      * Set the value of the _wantClientAuth property. This property is used
587      * internally when opening server sockets.
588      *
589      * @param wantClientAuth true if we want client certificate authentication.
590      * @see SSLServerSocket#setWantClientAuth
591      * @deprecated
592      */
593     @Deprecated
setWantClientAuth(boolean wantClientAuth)594     public void setWantClientAuth(boolean wantClientAuth)
595     {
596         _sslContextFactory.setWantClientAuth(wantClientAuth);
597     }
598 
599     /* ------------------------------------------------------------ */
600     /**
601      * Set the time in milliseconds for so_timeout during ssl handshaking
602      * @param msec a non-zero value will be used to set so_timeout during
603      * ssl handshakes. A zero value means the maxIdleTime is used instead.
604      */
setHandshakeTimeout(int msec)605     public void setHandshakeTimeout (int msec)
606     {
607         _handshakeTimeout = msec;
608     }
609 
610 
611     /* ------------------------------------------------------------ */
getHandshakeTimeout()612     public int getHandshakeTimeout ()
613     {
614         return _handshakeTimeout;
615     }
616 
617     /* ------------------------------------------------------------ */
618     public class SslConnectorEndPoint extends ConnectorEndPoint
619     {
SslConnectorEndPoint(Socket socket)620         public SslConnectorEndPoint(Socket socket) throws IOException
621         {
622             super(socket);
623         }
624 
625         @Override
shutdownOutput()626         public void shutdownOutput() throws IOException
627         {
628             close();
629         }
630 
631         @Override
shutdownInput()632         public void shutdownInput() throws IOException
633         {
634             close();
635         }
636 
637         @Override
run()638         public void run()
639         {
640             try
641             {
642                 int handshakeTimeout = getHandshakeTimeout();
643                 int oldTimeout = _socket.getSoTimeout();
644                 if (handshakeTimeout > 0)
645                     _socket.setSoTimeout(handshakeTimeout);
646 
647                 final SSLSocket ssl=(SSLSocket)_socket;
648                 ssl.addHandshakeCompletedListener(new HandshakeCompletedListener()
649                 {
650                     boolean handshook=false;
651                     public void handshakeCompleted(HandshakeCompletedEvent event)
652                     {
653                         if (handshook)
654                         {
655                             if (!_sslContextFactory.isAllowRenegotiate())
656                             {
657                                 LOG.warn("SSL renegotiate denied: "+ssl);
658                                 try{ssl.close();}catch(IOException e){LOG.warn(e);}
659                             }
660                         }
661                         else
662                             handshook=true;
663                     }
664                 });
665                 ssl.startHandshake();
666 
667                 if (handshakeTimeout>0)
668                     _socket.setSoTimeout(oldTimeout);
669 
670                 super.run();
671             }
672             catch (SSLException e)
673             {
674                 LOG.debug(e);
675                 try{close();}
676                 catch(IOException e2){LOG.ignore(e2);}
677             }
678             catch (IOException e)
679             {
680                 LOG.debug(e);
681                 try{close();}
682                 catch(IOException e2){LOG.ignore(e2);}
683             }
684         }
685     }
686 
687     /* ------------------------------------------------------------ */
688     /**
689      * Unsupported.
690      *
691      * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past)
692      * @deprecated
693      */
694     @Deprecated
getAlgorithm()695     public String getAlgorithm()
696     {
697         throw new UnsupportedOperationException();
698     }
699 
700     /* ------------------------------------------------------------ */
701     /**
702      * Unsupported.
703      *
704      * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past)
705      * @deprecated
706      */
707     @Deprecated
setAlgorithm(String algorithm)708     public void setAlgorithm(String algorithm)
709     {
710         throw new UnsupportedOperationException();
711     }
712 }
713