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