1
15 package com.amazonaws.http.apache.client.impl;
16
17 import com.amazonaws.SDKGlobalConfiguration;
18 import com.amazonaws.http.AmazonHttpClient;
19 import com.amazonaws.http.DelegatingDnsResolver;
20 import com.amazonaws.http.SystemPropertyTlsKeyManagersProvider;
21 import com.amazonaws.http.TlsKeyManagersProvider;
22 import com.amazonaws.http.client.ConnectionManagerFactory;
23 import com.amazonaws.http.conn.SdkPlainSocketFactory;
24 import com.amazonaws.http.conn.ssl.SdkTLSSocketFactory;
25 import com.amazonaws.http.settings.HttpClientSettings;
26 import com.amazonaws.internal.SdkSSLContext;
27 import javax.net.ssl.KeyManager;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.http.HttpHost;
31 import org.apache.http.config.ConnectionConfig;
32 import org.apache.http.config.Registry;
33 import org.apache.http.config.RegistryBuilder;
34 import org.apache.http.config.SocketConfig;
35 import org.apache.http.conn.HttpClientConnectionManager;
36 import org.apache.http.conn.socket.ConnectionSocketFactory;
37 import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
38 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
39 import org.apache.http.impl.conn.DefaultSchemePortResolver;
40 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
41 import org.apache.http.protocol.HttpContext;
42
43 import javax.net.ssl.HostnameVerifier;
44 import javax.net.ssl.SSLContext;
45 import javax.net.ssl.SSLSocket;
46 import javax.net.ssl.TrustManager;
47 import javax.net.ssl.X509TrustManager;
48 import java.io.IOException;
49 import java.net.InetSocketAddress;
50 import java.net.Socket;
51 import java.net.UnknownHostException;
52 import java.security.cert.CertificateException;
53 import java.security.cert.X509Certificate;
54 import java.util.concurrent.TimeUnit;
55
56
59 public class ApacheConnectionManagerFactory implements
60 ConnectionManagerFactory<HttpClientConnectionManager> {
61
62 private final Log LOG = LogFactory.getLog(AmazonHttpClient.class);
63
64 @Override
65 public HttpClientConnectionManager create(final HttpClientSettings settings) {
66 ConnectionSocketFactory sslsf = getPreferredSocketFactory(settings);
67
68 final PoolingHttpClientConnectionManager cm = new
69 PoolingHttpClientConnectionManager(
70 createSocketFactoryRegistry(sslsf),
71 null,
72 DefaultSchemePortResolver.INSTANCE,
73 new DelegatingDnsResolver(settings.getDnsResolver()),
74 settings.getConnectionPoolTTL(),
75 TimeUnit.MILLISECONDS);
76
77 cm.setValidateAfterInactivity(settings.getValidateAfterInactivityMillis());
78 cm.setDefaultMaxPerRoute(settings.getMaxConnections());
79 cm.setMaxTotal(settings.getMaxConnections());
80 cm.setDefaultSocketConfig(buildSocketConfig(settings));
81 cm.setDefaultConnectionConfig(buildConnectionConfig(settings));
82
83 return cm;
84 }
85
86 private ConnectionSocketFactory getPreferredSocketFactory(HttpClientSettings settings) {
87 ConnectionSocketFactory sslsf = settings.getApacheHttpClientConfig().getSslSocketFactory();
88
89 return sslsf != null
90 ? sslsf
91 : new SdkTLSSocketFactory(
92 SdkSSLContext.getPreferredSSLContext(getKeyManagers(settings), settings.getSecureRandom()),
93 getHostNameVerifier(settings));
94 }
95
96 private SocketConfig buildSocketConfig(HttpClientSettings settings) {
97 return SocketConfig.custom()
98 .setSoKeepAlive(settings.useTcpKeepAlive())
99 .setSoTimeout(settings.getSocketTimeout())
100 .setTcpNoDelay(true)
101 .build();
102 }
103
104 private ConnectionConfig buildConnectionConfig(HttpClientSettings settings) {
105
106 int socketBufferSize = Math.max(settings.getSocketBufferSize()[0],
107 settings.getSocketBufferSize()[1]);
108
109 return socketBufferSize <= 0
110 ? null
111 : ConnectionConfig.custom()
112 .setBufferSize(socketBufferSize)
113 .build();
114 }
115
116 private KeyManager[] getKeyManagers(HttpClientSettings settings) {
117 TlsKeyManagersProvider provider = settings.getTlsKeyMangersProvider();
118 if (provider == null) {
119 provider = new SystemPropertyTlsKeyManagersProvider();
120 }
121 return provider.getKeyManagers();
122 }
123
124 private HostnameVerifier getHostNameVerifier
125 (HttpClientSettings options) {
126
127 return options.useBrowserCompatibleHostNameVerifier()
128 ? SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
129 : SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER;
130 }
131
132 private Registry<ConnectionSocketFactory> createSocketFactoryRegistry(ConnectionSocketFactory sslSocketFactory) {
133
134
139 if (SDKGlobalConfiguration.isCertCheckingDisabled()) {
140 if (LOG.isWarnEnabled()) {
141 LOG.warn("SSL Certificate checking for endpoints has been " +
142 "explicitly disabled.");
143 }
144 sslSocketFactory = new TrustingSocketFactory();
145 }
146
147 return RegistryBuilder.<ConnectionSocketFactory>create()
148 .register("http", new SdkPlainSocketFactory())
149 .register("https", sslSocketFactory)
150 .build();
151 }
152
153
158 private static class TrustingSocketFactory implements
159 LayeredConnectionSocketFactory {
160
161 private SSLContext sslcontext = null;
162
163 private static SSLContext createSSLContext() throws IOException {
164 try {
165 SSLContext context = SSLContext.getInstance("TLS");
166 context.init(null, new TrustManager[]{new TrustingX509TrustManager()}, null);
167 return context;
168 } catch (Exception e) {
169 throw new IOException(e.getMessage(), e);
170 }
171 }
172
173 @Override
174 public Socket createLayeredSocket(Socket socket, String target, int port, HttpContext context) throws IOException, UnknownHostException {
175 return getSSLContext().getSocketFactory().createSocket(socket,
176 target, port, true);
177 }
178
179 @Override
180 public Socket createSocket(HttpContext context) throws IOException {
181 return getSSLContext().getSocketFactory().createSocket();
182 }
183
184 @Override
185 public Socket connectSocket(int connectTimeout, Socket sock, HttpHost host, InetSocketAddress remoteAddress, InetSocketAddress localAddress, HttpContext context) throws IOException {
186
187 SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock :
188 createSocket(context));
189 if (localAddress != null) sslsock.bind(localAddress);
190
191
192 sslsock.connect(remoteAddress, connectTimeout);
193
194
195 return sslsock;
196 }
197
198 private SSLContext getSSLContext() throws IOException {
199 if (this.sslcontext == null) this.sslcontext = createSSLContext();
200 return this.sslcontext;
201 }
202 }
203
204
208 private static class TrustingX509TrustManager implements X509TrustManager {
209 private static final X509Certificate[] X509_CERTIFICATES = new X509Certificate[0];
210
211 @Override
212 public X509Certificate[] getAcceptedIssuers() {
213 return X509_CERTIFICATES;
214 }
215
216 @Override
217 public void checkServerTrusted(X509Certificate[] chain, String authType)
218 throws CertificateException {
219
220 }
221
222 @Override
223 public void checkClientTrusted(X509Certificate[] chain, String authType)
224 throws CertificateException {
225
226 }
227 }
228 }
229