PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/com.atlassian.connector.commons/src/main/java/com/atlassian/theplugin/commons/thirdparty/apache/EasySSLProtocolSocketFactory.java

https://bitbucket.org/atlassian/connector-commons
Java | 317 lines | 169 code | 34 blank | 114 comment | 28 complexity | fd727b03b66b87a4518cde28ec1d35d0 MD5 | raw file
Possible License(s): Apache-2.0
  1. package com.atlassian.theplugin.commons.thirdparty.apache;
  2. /*
  3. * $HeadURL$
  4. * $Revision$
  5. * $Date$
  6. *
  7. * ====================================================================
  8. *
  9. * Licensed to the Apache Software Foundation (ASF) under one or more
  10. * contributor license agreements. See the NOTICE file distributed with
  11. * this work for additional information regarding copyright ownership.
  12. * The ASF licenses this file to You under the Apache License, Version 2.0
  13. * (the "License"); you may not use this file except in compliance with
  14. * the License. You may obtain a copy of the License at
  15. *
  16. * http://www.apache.org/licenses/LICENSE-2.0
  17. *
  18. * Unless required by applicable law or agreed to in writing, software
  19. * distributed under the License is distributed on an "AS IS" BASIS,
  20. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. * See the License for the specific language governing permissions and
  22. * limitations under the License.
  23. * ====================================================================
  24. *
  25. * This software consists of voluntary contributions made by many
  26. * individuals on behalf of the Apache Software Foundation. For more
  27. * information on the Apache Software Foundation, please see
  28. * <http://www.apache.org/>.
  29. *
  30. */
  31. import org.apache.commons.httpclient.ConnectTimeoutException;
  32. import org.apache.commons.httpclient.HttpClientError;
  33. import org.apache.commons.httpclient.params.HttpConnectionParams;
  34. import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
  35. import javax.net.SocketFactory;
  36. import javax.net.ssl.KeyManagerFactory;
  37. import javax.net.ssl.SSLContext;
  38. import javax.net.ssl.TrustManager;
  39. import javax.net.ssl.TrustManagerFactory;
  40. import javax.net.ssl.X509TrustManager;
  41. import java.io.File;
  42. import java.io.FileInputStream;
  43. import java.io.FileNotFoundException;
  44. import java.io.IOException;
  45. import java.net.InetAddress;
  46. import java.net.InetSocketAddress;
  47. import java.net.Socket;
  48. import java.net.SocketAddress;
  49. import java.net.UnknownHostException;
  50. import java.security.KeyStore;
  51. import java.security.KeyStoreException;
  52. import java.security.NoSuchAlgorithmException;
  53. import java.security.SecureRandom;
  54. import java.security.UnrecoverableKeyException;
  55. import java.security.cert.CertificateException;
  56. import static java.lang.System.getProperty;
  57. /**
  58. * <p>
  59. * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s
  60. * that accept self-signed certificates.
  61. * </p>
  62. * <p>
  63. * This socket factory SHOULD NOT be used for productive systems
  64. * due to security reasons, unless it is a concious decision and
  65. * you are perfectly aware of security implications of accepting
  66. * self-signed certificates
  67. * </p>
  68. * <p/>
  69. * <p>
  70. * Example of using custom protocol socket factory for a specific host:
  71. * <pre>
  72. * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
  73. * <p/>
  74. * HttpClient client = new HttpClient();
  75. * client.getHostConfiguration().setHost("localhost", 443, easyhttps);
  76. * // use relative url only
  77. * GetMethod httpget = new GetMethod("/");
  78. * client.executeMethod(httpget);
  79. * </pre>
  80. * </p>
  81. * <p>
  82. * Example of using custom protocol socket factory per default instead of the standard one:
  83. * <pre>
  84. * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
  85. * Protocol.registerProtocol("https", easyhttps);
  86. * <p/>
  87. * HttpClient client = new HttpClient();
  88. * GetMethod httpget = new GetMethod("https://localhost/");
  89. * client.executeMethod(httpget);
  90. * </pre>
  91. * </p>
  92. *
  93. * @author <a href="mailto:oleg -at- ural.ru">Oleg Kalnichevski</a>
  94. * <p/>
  95. * <p>
  96. * DISCLAIMER: HttpClient developers DO NOT actively support this component.
  97. * The component is provided as a reference material, which may be inappropriate
  98. * for use without additional customization.
  99. * </p>
  100. */
  101. public class EasySSLProtocolSocketFactory implements SecureProtocolSocketFactory {
  102. public final static int SSL_PORT = 443;
  103. private SSLContext sslcontext = null;
  104. //private Logger logger;
  105. /**
  106. * Constructor for EasySSLProtocolSocketFactory.
  107. */
  108. public EasySSLProtocolSocketFactory() {
  109. super();
  110. //this.logger = logger;
  111. }
  112. private SSLContext createEasySSLContext() {
  113. KeyManagerFactory kmf = null;
  114. try {
  115. final KeyStore keyStore = getKeyStore();
  116. final String p = getProperty("javax.net.ssl.keyStorePassword");
  117. if (keyStore != null && p != null) {
  118. kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
  119. kmf.init(keyStore, p.toCharArray() );
  120. TrustManagerFactory tmf =
  121. TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
  122. tmf.init(keyStore);
  123. }
  124. //the exception is not important
  125. } catch (KeyStoreException e) {
  126. } catch (NoSuchAlgorithmException e) {
  127. } catch (UnrecoverableKeyException e) {
  128. }
  129. try {
  130. SSLContext context = SSLContext.getInstance("SSL");
  131. context.init(
  132. kmf != null ? kmf.getKeyManagers() : null,
  133. new TrustManager[]{getTrustManager()},
  134. kmf != null ? new SecureRandom() : null);
  135. return context;
  136. } catch (Exception e) {
  137. //logger.error(e.getMessage(), e);
  138. throw new HttpClientError(e.toString());
  139. }
  140. }
  141. public static KeyStore getKeyStore() {
  142. KeyStore keyJKSStore = getKeyJKSStore(getProperty("javax.net.ssl.keyStore"), getProperty("javax.net.ssl.keyStorePassword"));
  143. KeyStore trust = getKeyJKSStore(getProperty("javax.net.ssl.trustStore"), getProperty("javax.net.ssl.trustStorePassword"));
  144. // if (keyJKSStore == null) {
  145. // try {
  146. // keyJKSStore = KeyStore.getInstance("JKS");
  147. //
  148. // } catch (KeyStoreException e) {
  149. // return null;
  150. // }
  151. // }
  152. try {
  153. if (trust != null && keyJKSStore != null && trust.size() > 0 && keyJKSStore.size() > 0) {
  154. try {
  155. while (trust.aliases().hasMoreElements()) {
  156. String alias = trust.aliases().nextElement();
  157. keyJKSStore.setCertificateEntry(alias, trust.getCertificate(alias));
  158. trust.deleteEntry(alias);
  159. }
  160. } catch (KeyStoreException e) {
  161. }
  162. }
  163. } catch (KeyStoreException e) {
  164. e.printStackTrace();
  165. }
  166. return keyJKSStore;
  167. }
  168. private static KeyStore getKeyJKSStore(String keyStoreFileName, String keyStorePassword) {
  169. KeyStore jKeyStore = null;
  170. try {
  171. if (keyStorePassword != null && keyStorePassword.length() > 0
  172. && keyStoreFileName != null && keyStoreFileName.length() > 0) {
  173. jKeyStore = KeyStore.getInstance("JKS");
  174. File file = new File(keyStoreFileName);
  175. FileInputStream inStream = new FileInputStream(file);
  176. jKeyStore.load(inStream, keyStorePassword.toCharArray());
  177. }
  178. } catch (KeyStoreException e) {
  179. } catch (FileNotFoundException e) {
  180. } catch (CertificateException e) {
  181. } catch (NoSuchAlgorithmException e) {
  182. } catch (IOException e) {
  183. }
  184. return jKeyStore;
  185. }
  186. protected X509TrustManager getTrustManager() throws NoSuchAlgorithmException, KeyStoreException {
  187. return new EasyX509TrustManager(getKeyStore());
  188. }
  189. private SSLContext getSSLContext() {
  190. if (this.sslcontext == null) {
  191. this.sslcontext = createEasySSLContext();
  192. }
  193. return this.sslcontext;
  194. }
  195. /**
  196. * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
  197. */
  198. public Socket createSocket(
  199. String host,
  200. int port,
  201. InetAddress clientHost,
  202. int clientPort)
  203. throws IOException, UnknownHostException {
  204. return getSSLContext().getSocketFactory().createSocket(
  205. host,
  206. port,
  207. clientHost,
  208. clientPort
  209. );
  210. }
  211. /**
  212. * Attempts to get a new socket connection to the given host within the given time limit.
  213. * <p>
  214. * To circumvent the limitations of older JREs that do not support connect timeout a
  215. * controller thread is executed. The controller thread attempts to create a new socket
  216. * within the given limit of time. If socket constructor does not return until the
  217. * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException}
  218. * </p>
  219. *
  220. * @param host the host name/IP
  221. * @param port the port on the host
  222. * @param params {@link HttpConnectionParams Http connection parameters}
  223. * @return Socket a new socket
  224. * @throws IOException if an I/O error occurs while creating the socket
  225. * @throws UnknownHostException if the IP address of the host cannot be
  226. * determined
  227. */
  228. public Socket createSocket(
  229. final String host,
  230. final int port,
  231. final InetAddress localAddress,
  232. final int localPort,
  233. final HttpConnectionParams params
  234. ) throws IOException, UnknownHostException, ConnectTimeoutException {
  235. if (params == null) {
  236. throw new IllegalArgumentException("Parameters may not be null");
  237. }
  238. int timeout = params.getConnectionTimeout();
  239. SocketFactory socketfactory = getSSLContext().getSocketFactory();
  240. if (timeout == 0) {
  241. return socketfactory.createSocket(host, port, localAddress, localPort);
  242. } else {
  243. Socket socket = socketfactory.createSocket();
  244. SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
  245. SocketAddress remoteaddr = new InetSocketAddress(host, port);
  246. socket.bind(localaddr);
  247. socket.connect(remoteaddr, timeout);
  248. return socket;
  249. }
  250. }
  251. /**
  252. * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
  253. */
  254. public Socket createSocket(String host, int port)
  255. throws IOException, UnknownHostException {
  256. return getSSLContext().getSocketFactory().createSocket(
  257. host,
  258. port
  259. );
  260. }
  261. /**
  262. * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
  263. */
  264. public Socket createSocket(
  265. Socket socket,
  266. String host,
  267. int port,
  268. boolean autoClose)
  269. throws IOException, UnknownHostException {
  270. return getSSLContext().getSocketFactory().createSocket(
  271. socket,
  272. host,
  273. port,
  274. autoClose
  275. );
  276. }
  277. public boolean equals(Object obj) {
  278. return ((obj != null) && obj.getClass().equals(EasySSLProtocolSocketFactory.class));
  279. }
  280. public int hashCode() {
  281. return EasySSLProtocolSocketFactory.class.hashCode();
  282. }
  283. }