1
2
3
4
5
6
7 package org.mule.transport.http;
8
9 import org.mule.api.MessagingException;
10 import org.mule.api.MuleMessage;
11 import org.mule.api.construct.FlowConstruct;
12 import org.mule.api.endpoint.InboundEndpoint;
13 import org.mule.api.lifecycle.CreateException;
14 import org.mule.api.transport.Connector;
15 import org.mule.config.i18n.CoreMessages;
16 import org.mule.transport.ConnectException;
17 import org.mule.transport.http.i18n.HttpMessages;
18 import org.mule.util.StringUtils;
19
20 import java.io.IOException;
21 import java.net.Socket;
22 import java.security.cert.Certificate;
23
24 import javax.net.ssl.HandshakeCompletedEvent;
25 import javax.net.ssl.HandshakeCompletedListener;
26 import javax.net.ssl.SSLPeerUnverifiedException;
27 import javax.net.ssl.SSLSocket;
28 import javax.resource.spi.work.Work;
29
30 import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch;
31 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
32
33 public class HttpsMessageReceiver extends HttpMessageReceiver
34 {
35 public HttpsMessageReceiver(Connector connector, FlowConstruct flow, InboundEndpoint endpoint)
36 throws CreateException
37 {
38 super(connector, flow, endpoint);
39 }
40
41 @Override
42 protected void doConnect() throws ConnectException
43 {
44 checkKeyStore();
45 super.doConnect();
46 }
47
48 protected void checkKeyStore() throws ConnectException
49 {
50 HttpsConnector httpsConnector = (HttpsConnector) connector;
51 String keyStore = httpsConnector.getKeyStore();
52 if (StringUtils.isBlank(keyStore))
53 {
54 throw new ConnectException(CoreMessages.objectIsNull("tls-key-store"), this);
55 }
56 }
57
58 @Override
59 protected Work createWork(Socket socket) throws IOException
60 {
61 return new HttpsWorker(socket);
62 }
63
64 private class HttpsWorker extends HttpWorker implements HandshakeCompletedListener
65 {
66 private Certificate[] peerCertificateChain;
67 private Certificate[] localCertificateChain;
68 private final CountDownLatch latch = new CountDownLatch(1);
69
70 public HttpsWorker(Socket socket) throws IOException
71 {
72 super(socket);
73 ((SSLSocket) socket).addHandshakeCompletedListener(this);
74 }
75
76 @Override
77 protected void preRouteMessage(MuleMessage message) throws MessagingException
78 {
79 try
80 {
81 long timeout = ((HttpsConnector) getConnector()).getSslHandshakeTimeout();
82 boolean handshakeComplete = latch.await(timeout, TimeUnit.MILLISECONDS);
83 if (!handshakeComplete)
84 {
85 throw new MessagingException(HttpMessages.sslHandshakeDidNotComplete(), message);
86 }
87 }
88 catch (InterruptedException e)
89 {
90 throw new MessagingException(HttpMessages.sslHandshakeDidNotComplete(),
91 message, e);
92 }
93
94 super.preRouteMessage(message);
95
96 if (peerCertificateChain != null)
97 {
98 message.setOutboundProperty(HttpsConnector.PEER_CERTIFICATES, peerCertificateChain);
99 }
100 if (localCertificateChain != null)
101 {
102 message.setOutboundProperty(HttpsConnector.LOCAL_CERTIFICATES, localCertificateChain);
103 }
104 }
105
106 public void handshakeCompleted(HandshakeCompletedEvent event)
107 {
108 try
109 {
110 localCertificateChain = event.getLocalCertificates();
111 try
112 {
113 peerCertificateChain = event.getPeerCertificates();
114 }
115 catch (SSLPeerUnverifiedException e)
116 {
117 logger.debug("Cannot get peer certificate chain: "+ e.getMessage());
118 }
119 }
120 finally
121 {
122 latch.countDown();
123 }
124 }
125 }
126 }