Advertisement
Guest User

Untitled

a guest
May 25th, 2012
350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.52 KB | None | 0 0
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19.  
  20. package org.apache.cxf.transport.https;
  21.  
  22. import java.io.IOException;
  23. import java.lang.reflect.Constructor;
  24. import java.lang.reflect.InvocationHandler;
  25. import java.lang.reflect.Method;
  26. import java.net.HttpURLConnection;
  27. import java.net.Proxy;
  28. import java.net.URL;
  29. import java.security.GeneralSecurityException;
  30. import java.util.logging.Handler;
  31. import java.util.logging.Logger;
  32.  
  33. import javax.net.ssl.HostnameVerifier;
  34. import javax.net.ssl.HttpsURLConnection;
  35. import javax.net.ssl.SSLContext;
  36. import javax.net.ssl.SSLSocketFactory;
  37.  
  38. import org.apache.cxf.common.logging.LogUtils;
  39. import org.apache.cxf.common.util.ReflectionInvokationHandler;
  40. import org.apache.cxf.configuration.jsse.TLSClientParameters;
  41.  
  42. /**
  43. * This HttpsURLConnectionFactory implements the HttpURLConnectionFactory
  44. * for using the given SSL Policy to configure TLS connections for "https:"
  45. * URLs.
  46. *
  47. */
  48. public class HttpsURLConnectionFactory {
  49.  
  50. /**
  51. * This constant holds the URL Protocol Identifier for HTTPS
  52. */
  53. public static final String HTTPS_URL_PROTOCOL_ID = "https";
  54.  
  55. private static final long serialVersionUID = 1L;
  56. private static final Logger LOG =
  57. LogUtils.getL7dLogger(HttpsURLConnectionFactory.class);
  58.  
  59. private static boolean weblogicWarned;
  60.  
  61. /**
  62. * Cache the last SSLContext to avoid recreation
  63. */
  64. SSLSocketFactory socketFactory;
  65.  
  66. /**
  67. * This constructor initialized the factory with the configured TLS
  68. * Client Parameters for the HTTPConduit for which this factory is used.
  69. */
  70. public HttpsURLConnectionFactory() {
  71. }
  72.  
  73. /**
  74. * Create a HttpURLConnection, proxified if necessary.
  75. *
  76. *
  77. * @param proxy This parameter is non-null if connection should be proxied.
  78. * @param url The target URL. This parameter must be an https url.
  79. *
  80. * @return The HttpsURLConnection for the given URL.
  81. * @throws IOException This exception is thrown if
  82. * the "url" is not "https" or other IOException
  83. * is thrown.
  84. *
  85. */
  86. public HttpURLConnection createConnection(TLSClientParameters tlsClientParameters,
  87. Proxy proxy, URL url) throws IOException {
  88.  
  89. HttpURLConnection connection =
  90. (HttpURLConnection) (proxy != null
  91. ? url.openConnection(proxy)
  92. : url.openConnection());
  93. if (HTTPS_URL_PROTOCOL_ID.equals(url.getProtocol())) {
  94.  
  95. if (tlsClientParameters == null) {
  96. tlsClientParameters = new TLSClientParameters();
  97. }
  98.  
  99. Exception ex = null;
  100. try {
  101. decorateWithTLS(tlsClientParameters, connection);
  102. } catch (Exception e) {
  103. ex = e;
  104. } finally {
  105. if (ex != null) {
  106. if (ex instanceof IOException) {
  107. throw (IOException) ex;
  108. }
  109. // use exception.initCause(ex) to be java 5 compatible
  110. IOException ioException = new IOException("Error while initializing secure socket");
  111. ioException.initCause(ex);
  112. throw ioException;
  113. }
  114. }
  115. }
  116.  
  117. return connection;
  118. }
  119.  
  120. /**
  121. * This method assigns the various TLS parameters on the HttpsURLConnection
  122. * from the TLS Client Parameters. Connection parameter is of supertype HttpURLConnection,
  123. * which allows internal cast to potentially divergent subtype (https) implementations.
  124. */
  125. protected synchronized void decorateWithTLS(TLSClientParameters tlsClientParameters,
  126. HttpURLConnection connection) throws GeneralSecurityException {
  127.  
  128. // always reload socketFactory from HttpsURLConnection.defaultSSLSocketFactory and
  129. // tlsClientParameters.sslSocketFactory to allow runtime configuration change
  130. if (tlsClientParameters.isUseHttpsURLConnectionDefaultSslSocketFactory()) {
  131. socketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
  132.  
  133. } else if (tlsClientParameters.getSSLSocketFactory() != null) {
  134. // see if an SSLSocketFactory was set. This allows easy interop
  135. // with not-yet-commons-ssl.jar, or even just people who like doing their
  136. // own JSSE.
  137. socketFactory = tlsClientParameters.getSSLSocketFactory();
  138.  
  139. } else if (socketFactory == null) {
  140. // ssl socket factory not yet instantiated, create a new one with tlsClientParameters's Trust
  141. // Managers, Key Managers, etc
  142.  
  143. String provider = tlsClientParameters.getJsseProvider();
  144.  
  145. String protocol = tlsClientParameters.getSecureSocketProtocol() != null ? tlsClientParameters
  146. .getSecureSocketProtocol() : "TLS";
  147.  
  148. SSLContext ctx = provider == null ? SSLContext.getInstance(protocol) : SSLContext
  149. .getInstance(protocol, provider);
  150. ctx.getClientSessionContext().setSessionTimeout(tlsClientParameters.getSslCacheTimeout());
  151. ctx.init(tlsClientParameters.getKeyManagers(), tlsClientParameters.getTrustManagers(),
  152. tlsClientParameters.getSecureRandom());
  153.  
  154. // The "false" argument means opposite of exclude.
  155. String[] cipherSuites = SSLUtils.getCiphersuites(tlsClientParameters.getCipherSuites(), SSLUtils
  156. .getSupportedCipherSuites(ctx), tlsClientParameters.getCipherSuitesFilter(), LOG, false);
  157. // The SSLSocketFactoryWrapper enables certain cipher suites
  158. // from the policy.
  159. socketFactory = new SSLSocketFactoryWrapper(ctx.getSocketFactory(), cipherSuites,
  160. tlsClientParameters.getSecureSocketProtocol());
  161. } else {
  162. // ssl socket factory already initialized, reuse it to benefit of keep alive
  163. }
  164.  
  165.  
  166. HostnameVerifier verifier;
  167. if (tlsClientParameters.isUseHttpsURLConnectionDefaultHostnameVerifier()) {
  168. verifier = HttpsURLConnection.getDefaultHostnameVerifier();
  169. } else if (tlsClientParameters.isDisableCNCheck()) {
  170. verifier = CertificateHostnameVerifier.ALLOW_ALL;
  171. } else {
  172. verifier = CertificateHostnameVerifier.DEFAULT;
  173. }
  174.  
  175. if (connection instanceof HttpsURLConnection) {
  176. // handle the expected case (javax.net.ssl)
  177. HttpsURLConnection conn = (HttpsURLConnection) connection;
  178. conn.setHostnameVerifier(verifier);
  179. conn.setSSLSocketFactory(socketFactory);
  180. } else {
  181. // handle the deprecated sun case and other possible hidden API's
  182. // that are similar to the Sun cases
  183. try {
  184. Method method = connection.getClass().getMethod("getHostnameVerifier");
  185.  
  186. InvocationHandler handler = new ReflectionInvokationHandler(verifier) {
  187. public Object invoke(Object proxy,
  188. Method method,
  189. Object[] args) throws Throwable {
  190. try {
  191. return super.invoke(proxy, method, args);
  192. } catch (Exception ex) {
  193. return true;
  194. }
  195. }
  196. };
  197. Object proxy = java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader(),
  198. new Class[] {method.getReturnType()},
  199. handler);
  200.  
  201. method = connection.getClass().getMethod("setHostnameVerifier", method.getReturnType());
  202. method.invoke(connection, proxy);
  203. } catch (Exception ex) {
  204. //Ignore this one
  205. }
  206. try {
  207. Method getSSLSocketFactory = connection.getClass().getMethod("getSSLSocketFactory");
  208. Method setSSLSocketFactory = connection.getClass()
  209. .getMethod("setSSLSocketFactory", getSSLSocketFactory.getReturnType());
  210. if (getSSLSocketFactory.getReturnType().isInstance(socketFactory)) {
  211. setSSLSocketFactory.invoke(connection, socketFactory);
  212. } else {
  213. //need to see if we can create one - mostly the weblogic case. The
  214. //weblogic SSLSocketFactory has a protected constructor that can take
  215. //a JSSE SSLSocketFactory so we'll try and use that
  216. Constructor c = getSSLSocketFactory.getReturnType()
  217. .getDeclaredConstructor(SSLSocketFactory.class);
  218. c.setAccessible(true);
  219. setSSLSocketFactory.invoke(connection, c.newInstance(socketFactory));
  220. //patch to force setting the local identity in sslclientinfo to remain compatible with weblogic 10.3
  221. //because there is a bug in weblogic who destroys this connectionfactory when using a proxy
  222. if (connection instanceof weblogic.net.http.HttpsURLConnection) {
  223. javax.net.ssl.KeyManager [] keymgrs = tlsClientParameters.getKeyManagers();
  224. javax.net.ssl.X509KeyManager keymgr = null;
  225. //scans the keymanagers and set the keymanager if type is X509KeyManager
  226. for (int i=0;i< keymgrs.length && keymgr == null;i++) {
  227. if (keymgrs != null && keymgrs[i] != null && keymgrs[i] instanceof javax.net.ssl.X509KeyManager)
  228. keymgr = (javax.net.ssl.X509KeyManager)(keymgrs[i]);
  229. }
  230. if (keymgr !=null) {
  231. //i think only RSA is needed in this case
  232. String [] aliases = keymgr.getClientAliases("RSA",null);
  233. String alias=null;
  234. //take the first alias
  235. if (aliases != null && aliases.length > 0 && aliases[0]!=null) {
  236. alias=aliases[0];
  237. java.security.PrivateKey privkey = keymgr.getPrivateKey(alias);
  238. java.security.cert.X509Certificate [] chain = keymgr.getCertificateChain(alias);
  239. //here we use the only weblogic method in the cxf code -> very dirty maybe need to use invoke to avoid static compiling
  240. ((weblogic.net.http.HttpsURLConnection)connection).loadLocalIdentity(chain, privkey);
  241. }
  242. }
  243. }
  244. }
  245. } catch (Exception ex) {
  246. if (connection.getClass().getName().contains("weblogic")) {
  247. if (!weblogicWarned) {
  248. weblogicWarned = true;
  249. LOG.warning("Could not configure SSLSocketFactory on Weblogic. "
  250. + " Use the Weblogic control panel to configure the SSL settings.");
  251. }
  252. return;
  253. }
  254. //if we cannot set the SSLSocketFactor, we're in serious trouble.
  255. throw new IllegalArgumentException("Error decorating connection class "
  256. + connection.getClass().getName(), ex);
  257. }
  258. }
  259. }
  260.  
  261. /*
  262. * For development and testing only
  263. */
  264. protected void addLogHandler(Handler handler) {
  265. LOG.addHandler(handler);
  266. }
  267.  
  268. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement