Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
EasySSLProtocolSocketFactory |
|
| 2.0;2 |
1 | /* | |
2 | * ==================================================================== | |
3 | * | |
4 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
5 | * contributor license agreements. See the NOTICE file distributed with | |
6 | * this work for additional information regarding copyright ownership. | |
7 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
8 | * (the "License"); you may not use this file except in compliance with | |
9 | * the License. You may obtain a copy of the License at | |
10 | * | |
11 | * http://www.apache.org/licenses/LICENSE-2.0 | |
12 | * | |
13 | * Unless required by applicable law or agreed to in writing, software | |
14 | * distributed under the License is distributed on an "AS IS" BASIS, | |
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
16 | * See the License for the specific language governing permissions and | |
17 | * limitations under the License. | |
18 | * ==================================================================== | |
19 | * | |
20 | * This software consists of voluntary contributions made by many | |
21 | * individuals on behalf of the Apache Software Foundation. For more | |
22 | * information on the Apache Software Foundation, please see | |
23 | * <http://www.apache.org/>. | |
24 | * | |
25 | */ | |
26 | ||
27 | package org.apache.commons.httpclient.contrib.ssl; | |
28 | ||
29 | import java.io.IOException; | |
30 | import java.net.InetAddress; | |
31 | import java.net.InetSocketAddress; | |
32 | import java.net.Socket; | |
33 | import java.net.SocketAddress; | |
34 | import java.net.UnknownHostException; | |
35 | ||
36 | import javax.net.SocketFactory; | |
37 | import javax.net.ssl.SSLContext; | |
38 | import javax.net.ssl.TrustManager; | |
39 | ||
40 | import org.apache.commons.httpclient.ConnectTimeoutException; | |
41 | import org.apache.commons.httpclient.HttpClientError; | |
42 | import org.apache.commons.httpclient.params.HttpConnectionParams; | |
43 | import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; | |
44 | import org.apache.commons.logging.Log; | |
45 | import org.apache.commons.logging.LogFactory; | |
46 | ||
47 | /** | |
48 | * <p> | |
49 | * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s | |
50 | * that accept self-signed certificates. | |
51 | * </p> | |
52 | * <p> | |
53 | * This socket factory SHOULD NOT be used for productive systems | |
54 | * due to security reasons, unless it is a concious decision and | |
55 | * you are perfectly aware of security implications of accepting | |
56 | * self-signed certificates | |
57 | * </p> | |
58 | * | |
59 | * <p> | |
60 | * Example of using custom protocol socket factory for a specific host: | |
61 | * <pre> | |
62 | * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443); | |
63 | * | |
64 | * URI uri = new URI("https://localhost/", true); | |
65 | * // use relative url only | |
66 | * GetMethod httpget = new GetMethod(uri.getPathQuery()); | |
67 | * HostConfiguration hc = new HostConfiguration(); | |
68 | * hc.setHost(uri.getHost(), uri.getPort(), easyhttps); | |
69 | * HttpClient client = new HttpClient(); | |
70 | * client.executeMethod(hc, httpget); | |
71 | * </pre> | |
72 | * </p> | |
73 | * <p> | |
74 | * Example of using custom protocol socket factory per default instead of the standard one: | |
75 | * <pre> | |
76 | * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443); | |
77 | * Protocol.registerProtocol("https", easyhttps); | |
78 | * | |
79 | * HttpClient client = new HttpClient(); | |
80 | * GetMethod httpget = new GetMethod("https://localhost/"); | |
81 | * client.executeMethod(httpget); | |
82 | * </pre> | |
83 | * </p> | |
84 | * | |
85 | * @author <a href="mailto:oleg -at- ural.ru">Oleg Kalnichevski</a> | |
86 | * | |
87 | * <p> | |
88 | * DISCLAIMER: HttpClient developers DO NOT actively support this component. | |
89 | * The component is provided as a reference material, which may be inappropriate | |
90 | * for use without additional customization. | |
91 | * </p> | |
92 | */ | |
93 | ||
94 | public class EasySSLProtocolSocketFactory implements SecureProtocolSocketFactory { | |
95 | ||
96 | /** Log object for this class. */ | |
97 | 0 | private static final Log LOG = LogFactory.getLog(EasySSLProtocolSocketFactory.class); |
98 | ||
99 | 0 | private SSLContext sslcontext = null; |
100 | ||
101 | /** | |
102 | * Constructor for EasySSLProtocolSocketFactory. | |
103 | */ | |
104 | public EasySSLProtocolSocketFactory() { | |
105 | 0 | super(); |
106 | 0 | } |
107 | ||
108 | private static SSLContext createEasySSLContext() { | |
109 | try { | |
110 | 0 | SSLContext context = SSLContext.getInstance("SSL"); |
111 | 0 | context.init( |
112 | null, | |
113 | new TrustManager[] {new EasyX509TrustManager(null)}, | |
114 | null); | |
115 | 0 | return context; |
116 | 0 | } catch (Exception e) { |
117 | 0 | LOG.error(e.getMessage(), e); |
118 | 0 | throw new HttpClientError(e.toString()); |
119 | } | |
120 | } | |
121 | ||
122 | private SSLContext getSSLContext() { | |
123 | 0 | if (this.sslcontext == null) { |
124 | 0 | this.sslcontext = createEasySSLContext(); |
125 | } | |
126 | 0 | return this.sslcontext; |
127 | } | |
128 | ||
129 | /** | |
130 | * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) | |
131 | */ | |
132 | public Socket createSocket( | |
133 | String host, | |
134 | int port, | |
135 | InetAddress clientHost, | |
136 | int clientPort) | |
137 | throws IOException, UnknownHostException { | |
138 | ||
139 | 0 | return getSSLContext().getSocketFactory().createSocket( |
140 | host, | |
141 | port, | |
142 | clientHost, | |
143 | clientPort | |
144 | ); | |
145 | } | |
146 | ||
147 | /** | |
148 | * Attempts to get a new socket connection to the given host within the given time limit. | |
149 | * <p> | |
150 | * To circumvent the limitations of older JREs that do not support connect timeout a | |
151 | * controller thread is executed. The controller thread attempts to create a new socket | |
152 | * within the given limit of time. If socket constructor does not return until the | |
153 | * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException} | |
154 | * </p> | |
155 | * | |
156 | * @param host the host name/IP | |
157 | * @param port the port on the host | |
158 | * @param clientHost the local host name/IP to bind the socket to | |
159 | * @param clientPort the port on the local machine | |
160 | * @param params {@link HttpConnectionParams Http connection parameters} | |
161 | * | |
162 | * @return Socket a new socket | |
163 | * | |
164 | * @throws IOException if an I/O error occurs while creating the socket | |
165 | * @throws UnknownHostException if the IP address of the host cannot be | |
166 | * determined | |
167 | */ | |
168 | public Socket createSocket( | |
169 | final String host, | |
170 | final int port, | |
171 | final InetAddress localAddress, | |
172 | final int localPort, | |
173 | final HttpConnectionParams params | |
174 | ) throws IOException, UnknownHostException, ConnectTimeoutException { | |
175 | 0 | if (params == null) { |
176 | 0 | throw new IllegalArgumentException("Parameters may not be null"); |
177 | } | |
178 | 0 | int timeout = params.getConnectionTimeout(); |
179 | 0 | SocketFactory socketfactory = getSSLContext().getSocketFactory(); |
180 | 0 | if (timeout == 0) { |
181 | 0 | return socketfactory.createSocket(host, port, localAddress, localPort); |
182 | } else { | |
183 | 0 | Socket socket = socketfactory.createSocket(); |
184 | 0 | SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); |
185 | 0 | SocketAddress remoteaddr = new InetSocketAddress(host, port); |
186 | 0 | socket.bind(localaddr); |
187 | 0 | socket.connect(remoteaddr, timeout); |
188 | 0 | return socket; |
189 | } | |
190 | } | |
191 | ||
192 | /** | |
193 | * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int) | |
194 | */ | |
195 | public Socket createSocket(String host, int port) | |
196 | throws IOException, UnknownHostException { | |
197 | 0 | return getSSLContext().getSocketFactory().createSocket( |
198 | host, | |
199 | port | |
200 | ); | |
201 | } | |
202 | ||
203 | /** | |
204 | * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean) | |
205 | */ | |
206 | public Socket createSocket( | |
207 | Socket socket, | |
208 | String host, | |
209 | int port, | |
210 | boolean autoClose) | |
211 | throws IOException, UnknownHostException { | |
212 | 0 | return getSSLContext().getSocketFactory().createSocket( |
213 | socket, | |
214 | host, | |
215 | port, | |
216 | autoClose | |
217 | ); | |
218 | } | |
219 | ||
220 | public boolean equals(Object obj) { | |
221 | 0 | return ((obj != null) && obj.getClass().equals(EasySSLProtocolSocketFactory.class)); |
222 | } | |
223 | ||
224 | public int hashCode() { | |
225 | 0 | return EasySSLProtocolSocketFactory.class.hashCode(); |
226 | } | |
227 | ||
228 | } |