View Javadoc

1   /*
2    * $Id: SslMessageReceiver.java 19191 2010-08-25 21:05:23Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transport.ssl;
12  
13  import org.mule.api.MuleMessage;
14  import org.mule.api.construct.FlowConstruct;
15  import org.mule.api.endpoint.InboundEndpoint;
16  import org.mule.api.lifecycle.CreateException;
17  import org.mule.api.transport.Connector;
18  import org.mule.transport.AbstractMessageReceiver;
19  import org.mule.transport.tcp.TcpMessageReceiver;
20  
21  import java.io.IOException;
22  import java.net.Socket;
23  import java.security.cert.Certificate;
24  
25  import javax.net.ssl.HandshakeCompletedEvent;
26  import javax.net.ssl.HandshakeCompletedListener;
27  import javax.net.ssl.SSLPeerUnverifiedException;
28  import javax.net.ssl.SSLSocket;
29  import javax.resource.spi.work.Work;
30  
31  import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch;
32  import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
33  
34  
35  public class SslMessageReceiver extends TcpMessageReceiver implements HandshakeCompletedListener
36  {
37  
38      // We must wait for handshake to complete before sending message, as the callback
39      // sets important properties. The wait period is arbitrary, but the two threads
40      // are approximately synchronized (handshake completes before/at same time as
41      // message is received) so value should not be critical
42      private CountDownLatch handshakeComplete = new CountDownLatch(1);
43      
44      private Certificate[] peerCertificateChain;
45      private Certificate[] localCertificateChain;
46  
47      public SslMessageReceiver(Connector connector, FlowConstruct flowConstruct, InboundEndpoint endpoint)
48              throws CreateException
49      {
50          super(connector, flowConstruct, endpoint);
51      }
52  
53      protected Work createWork(Socket socket) throws IOException
54      {
55          return new SslWorker(socket, this);
56      }
57  
58      private void preRoute(MuleMessage message) throws Exception
59      {
60          long sslHandshakeTimeout = ((SslConnector) getConnector()).getSslHandshakeTimeout();
61          boolean rc = handshakeComplete.await(sslHandshakeTimeout, TimeUnit.MILLISECONDS);
62          if (rc == false)
63          {
64              throw new IllegalStateException("Handshake did not complete");
65          }
66  
67          if (peerCertificateChain != null)
68          {
69              message.setOutboundProperty(SslConnector.PEER_CERTIFICATES, peerCertificateChain);
70          }
71          if (localCertificateChain != null)
72          {
73              message.setOutboundProperty(SslConnector.LOCAL_CERTIFICATES, localCertificateChain);
74          }
75      }
76  
77      public void handshakeCompleted(HandshakeCompletedEvent event)
78      {
79          try
80          {
81              localCertificateChain = event.getLocalCertificates();
82              try
83              {
84                  peerCertificateChain = event.getPeerCertificates();
85              }
86              catch (SSLPeerUnverifiedException e)
87              {
88                  logger.debug("Cannot get peer certificate chain: "+ e.getMessage());
89              }
90          }
91          finally
92          {
93              handshakeComplete.countDown();
94          }
95      }
96  
97      protected class SslWorker extends TcpWorker
98      {
99          public SslWorker(Socket socket, AbstractMessageReceiver receiver) throws IOException
100         {
101             super(socket, receiver);
102             ((SSLSocket) socket).addHandshakeCompletedListener(SslMessageReceiver.this);
103         }
104 
105         @Override
106         protected void preRouteMuleMessage(MuleMessage message) throws Exception
107         {
108             super.preRouteMuleMessage(message);
109 
110             preRoute(message);
111         }
112 
113         @Override
114         protected void shutdownSocket() throws IOException
115         {
116             // SSL Sockets don't support shutdownSocket
117         }
118     }
119     
120 }