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