| author | Steffen Pingel | 2011-12-23 08:42:32 (EST) |
|---|---|---|
| committer | Steffen Pingel | 2011-12-23 08:42:32 (EST) |
| commit | 3b1f5eb4a5487469283a60c903f0b87d33816462 (patch) (side-by-side diff) | |
| tree | 47fda6d758c92e69652d77eac027b27e12464abd | |
| parent | 62cd96c0aaadce09717f5ecd2322b9985feb67e9 (diff) | |
| download | org.eclipse.mylyn.commons-3b1f5eb4a5487469283a60c903f0b87d33816462.zip org.eclipse.mylyn.commons-3b1f5eb4a5487469283a60c903f0b87d33816462.tar.gz org.eclipse.mylyn.commons-3b1f5eb4a5487469283a60c903f0b87d33816462.tar.bz2 | |
NEW - bug 317907: provide support for password prompting and
certificates
https://bugs.eclipse.org/bugs/show_bug.cgi?id=317907
Change-Id: Ic7124737ab6807ba537ba133f65469048c1cab44
7 files changed, 254 insertions, 64 deletions
diff --git a/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/net/NetUtil.java b/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/net/NetUtil.java index 376640e..7e8ff89 100644 --- a/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/net/NetUtil.java +++ b/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/net/NetUtil.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; import org.eclipse.core.net.proxy.IProxyData; import org.eclipse.core.net.proxy.IProxyService; @@ -45,12 +44,10 @@ import org.eclipse.osgi.util.NLS; */ public class NetUtil { - public static final int HTTPS_PORT = 443; + private static final int HTTPS_PORT = 443; private static final int HTTP_PORT = 80; - private SSLSocketFactory socketFactory; - private final static String[] enabledProtocols; private final static AtomicBoolean loggedEnabledProtocolsException = new AtomicBoolean(); diff --git a/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/net/SslCertificateException.java b/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/net/SslCertificateException.java new file mode 100644 index 0000000..dfd8306 --- a/dev/null +++ b/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/net/SslCertificateException.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009 BREDEX GmbH. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * BREDEX GmbH - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.commons.core.net; + +import java.io.IOException; + +/** + * Indicates that the access to a certificate-file failed. + * + * @author Torsten Kalix + * @since 3.7 + */ +public class SslCertificateException extends IOException { + + private static final long serialVersionUID = 1L; + + public SslCertificateException() { + } + + public SslCertificateException(String message) { + super(message); + } + +} diff --git a/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/net/SslSupport.java b/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/net/SslSupport.java new file mode 100644 index 0000000..f70d848 --- a/dev/null +++ b/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/net/SslSupport.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + * BREDEX GmbH - fix for bug 295050 + *******************************************************************************/ + +package org.eclipse.mylyn.commons.core.net; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; + +/** + * Provides support for managing SSL connections. + * + * @author Steffen Pingel + * @author Torsten Kalix + * @since 3.7 + */ +public class SslSupport { + + private static final String KEY_STORE_FILE_NAME = "javax.net.ssl.keyStore"; //$NON-NLS-1$ + + private static final String KEY_STORE_PASSWORD = "javax.net.ssl.keyStorePassword"; //$NON-NLS-1$ + + private static final String KEY_STORE_TYPE = "javax.net.ssl.keyStoreType"; //$NON-NLS-1$ + + private final String keyStoreFileName; + + private final String keyStorePassword; + + private final String keyStoreType; + + private SSLSocketFactory socketFactory; + + private final TrustManager[] trustManagers; + + public SslSupport(TrustManager[] trustManagers) { + this(trustManagers, System.getProperty(KEY_STORE_FILE_NAME), System.getProperty(KEY_STORE_PASSWORD), + System.getProperty(KEY_STORE_TYPE)); + } + + public SslSupport(TrustManager[] trustManagers, String keyStoreFileName, String keyStorePassword, + String keyStoreType) { + this.trustManagers = trustManagers; + this.keyStoreFileName = keyStoreFileName; + this.keyStorePassword = keyStorePassword; + this.keyStoreType = keyStoreType; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + SslSupport other = (SslSupport) obj; + if (keyStoreFileName == null) { + if (other.keyStoreFileName != null) { + return false; + } + } else if (!keyStoreFileName.equals(other.keyStoreFileName)) { + return false; + } + if (keyStorePassword == null) { + if (other.keyStorePassword != null) { + return false; + } + } else if (!keyStorePassword.equals(other.keyStorePassword)) { + return false; + } + if (keyStoreType == null) { + if (other.keyStoreType != null) { + return false; + } + } else if (!keyStoreType.equals(other.keyStoreType)) { + return false; + } + return true; + } + + public synchronized SSLSocketFactory getSocketFactory() throws IOException { + if (socketFactory == null) { + KeyManager[] keyManagers = null; + + // load keystore from file + if (keyStoreFileName != null && keyStorePassword != null) { + try { + if (keyStoreType != null) { + keyManagers = openKeyStore(keyStoreType); + } else { + try { + keyManagers = openKeyStore(KeyStore.getDefaultType()); + } catch (Exception e) { + keyManagers = openKeyStore("pkcs12"); //$NON-NLS-1$ + } + } + } catch (Exception cause) { + IOException e = new SslCertificateException(); + e.initCause(cause); + throw e; + } + } + + try { + SSLContext sslContext = SSLContext.getInstance("SSL"); //$NON-NLS-1$ + sslContext.init(keyManagers, trustManagers, null); + + this.socketFactory = sslContext.getSocketFactory(); + } catch (Exception cause) { + IOException e = new SslCertificateException(); + e.initCause(cause); + throw e; + } + } + return socketFactory; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((keyStoreFileName == null) ? 0 : keyStoreFileName.hashCode()); + result = prime * result + ((keyStorePassword == null) ? 0 : keyStorePassword.hashCode()); + result = prime * result + ((keyStoreType == null) ? 0 : keyStoreType.hashCode()); + return result; + } + + private KeyManager[] openKeyStore(String type) throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException, FileNotFoundException, UnrecoverableKeyException { + KeyStore keyStore = KeyStore.getInstance(type); + char[] password = keyStorePassword.toCharArray(); + keyStore.load(new FileInputStream(keyStoreFileName), password); + + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, password); + return keyManagerFactory.getKeyManagers(); + } + +} diff --git a/org.eclipse.mylyn.commons.repositories.core/src/org/eclipse/mylyn/commons/repositories/core/RepositoryLocation.java b/org.eclipse.mylyn.commons.repositories.core/src/org/eclipse/mylyn/commons/repositories/core/RepositoryLocation.java index e2c9bfb..8932475 100644 --- a/org.eclipse.mylyn.commons.repositories.core/src/org/eclipse/mylyn/commons/repositories/core/RepositoryLocation.java +++ b/org.eclipse.mylyn.commons.repositories.core/src/org/eclipse/mylyn/commons/repositories/core/RepositoryLocation.java @@ -35,6 +35,7 @@ import org.eclipse.mylyn.internal.commons.repositories.core.LocationService; /** * @author Steffen Pingel */ +// FIXME add synchronization public class RepositoryLocation extends PlatformObject { private static final String AUTH_HTTP = "org.eclipse.mylyn.tasklist.repositories.httpauth"; //$NON-NLS-1$ diff --git a/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/CommonHttpClient.java b/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/CommonHttpClient.java index a27c12d..49ad279 100644 --- a/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/CommonHttpClient.java +++ b/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/CommonHttpClient.java @@ -62,11 +62,16 @@ public class CommonHttpClient { protected void authenticate(IOperationMonitor monitor) throws IOException { } + protected ClientConnectionManager createHttpClientConnectionManager() { + // FIXME handle certificate authentication + return HttpUtil.getConnectionManager(); + } + protected AbstractHttpClient createHttpClient(String userAgent) { AbstractHttpClient client = new ContentEncodingHttpClient() { @Override protected ClientConnectionManager createClientConnectionManager() { - return HttpUtil.getConnectionManager(); + return CommonHttpClient.this.createHttpClientConnectionManager(); } }; HttpUtil.configureClient(client, userAgent); diff --git a/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/PollingProtocolSocketFactory.java b/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/PollingProtocolSocketFactory.java index 35be6fa..32087f2 100644 --- a/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/PollingProtocolSocketFactory.java +++ b/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/PollingProtocolSocketFactory.java @@ -33,7 +33,7 @@ class PollingProtocolSocketFactory implements SchemeSocketFactory { private final static SocketFactory factory = SocketFactory.getDefault(); public Socket createSocket(HttpParams params) throws IOException { - return factory.createSocket(); + return NetUtil.configureSocket(factory.createSocket()); } public Socket connectSocket(Socket sock, InetSocketAddress remoteAddress, InetSocketAddress localAddress, @@ -43,7 +43,7 @@ class PollingProtocolSocketFactory implements SchemeSocketFactory { throw new IllegalArgumentException("Parameters may not be null"); //$NON-NLS-1$ } - final Socket socket = sock != null ? sock : factory.createSocket(); + final Socket socket = sock != null ? sock : NetUtil.configureSocket(factory.createSocket()); int connTimeout = HttpConnectionParams.getConnectionTimeout(params); @@ -55,4 +55,5 @@ class PollingProtocolSocketFactory implements SchemeSocketFactory { public boolean isSecure(Socket sock) throws IllegalArgumentException { return false; } + } diff --git a/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/PollingSslProtocolSocketFactory.java b/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/PollingSslProtocolSocketFactory.java index c247814..aa3aa6d 100644 --- a/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/PollingSslProtocolSocketFactory.java +++ b/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/PollingSslProtocolSocketFactory.java @@ -11,16 +11,11 @@ package org.eclipse.mylyn.commons.repositories.http.core; -import java.io.FileInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; -import java.security.KeyStore; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; @@ -30,61 +25,26 @@ import org.apache.http.conn.scheme.LayeredSchemeSocketFactory; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.eclipse.core.runtime.Assert; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.commons.core.net.NetUtil; +import org.eclipse.mylyn.commons.core.net.SslSupport; import org.eclipse.mylyn.commons.core.net.TrustAllTrustManager; import org.eclipse.mylyn.commons.core.operations.MonitoredOperation; /** * Provides support for managing SSL connections. * - * @author Nathan Hapke - * @author Rob Elves * @author Steffen Pingel */ class PollingSslProtocolSocketFactory implements LayeredSchemeSocketFactory { - private static final String KEY_STORE = "javax.net.ssl.keyStore"; //$NON-NLS-1$ - - private static final String KEY_STORE_PASSWORD = "javax.net.ssl.keyStorePassword"; //$NON-NLS-1$ - - private static final String KEY_STORE_TYPE = "javax.net.ssl.keyStoreType"; //$NON-NLS-1$ - - private final boolean hasKeyManager; - - private SSLSocketFactory socketFactory; + private final SslSupport sslSupport; public PollingSslProtocolSocketFactory() { - KeyManager[] keymanagers = null; - if (System.getProperty(KEY_STORE) != null && System.getProperty(KEY_STORE_PASSWORD) != null) { - try { - String type = System.getProperty(KEY_STORE_TYPE, KeyStore.getDefaultType()); - KeyStore keyStore = KeyStore.getInstance(type); - char[] password = System.getProperty(KEY_STORE_PASSWORD).toCharArray(); - keyStore.load(new FileInputStream(System.getProperty(KEY_STORE)), password); - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - keyManagerFactory.init(keyStore, password); - keymanagers = keyManagerFactory.getKeyManagers(); - } catch (Exception e) { - StatusHandler.log(new Status(IStatus.ERROR, HttpUtil.ID_PLUGIN, "Could not initialize keystore", e)); //$NON-NLS-1$ - } - } - - hasKeyManager = keymanagers != null; - - try { - SSLContext sslContext = SSLContext.getInstance("SSL"); //$NON-NLS-1$ - sslContext.init(keymanagers, new TrustManager[] { new TrustAllTrustManager() }, null); - this.socketFactory = sslContext.getSocketFactory(); - } catch (Exception e) { - StatusHandler.log(new Status(IStatus.ERROR, HttpUtil.ID_PLUGIN, "Could not initialize SSL context", e)); //$NON-NLS-1$ - } + this(new SslSupport(new TrustManager[] { new TrustAllTrustManager() })); } - public Socket createSocket(HttpParams params) throws IOException { - return NetUtil.configureSocket(getSocketFactory().createSocket()); + public PollingSslProtocolSocketFactory(SslSupport sslSupport) { + this.sslSupport = sslSupport; } public Socket connectSocket(Socket sock, InetSocketAddress remoteAddress, InetSocketAddress localAddress, @@ -98,6 +58,49 @@ class PollingSslProtocolSocketFactory implements LayeredSchemeSocketFactory { return socket; } + public Socket createLayeredSocket(Socket socket, String target, int port, boolean autoClose) throws IOException, + UnknownHostException { + return NetUtil.configureSocket(getSocketFactory().createSocket(socket, target, port, autoClose)); + } + + public Socket createSocket(HttpParams params) throws IOException { + return NetUtil.configureSocket(getSocketFactory().createSocket()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + PollingSslProtocolSocketFactory other = (PollingSslProtocolSocketFactory) obj; + if (sslSupport == null) { + if (other.sslSupport != null) { + return false; + } + } else if (!sslSupport.equals(other.sslSupport)) { + return false; + } + return true; + } + + public SSLSocketFactory getSocketFactory() throws IOException { + return sslSupport.getSocketFactory(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((sslSupport == null) ? 0 : sslSupport.hashCode()); + return result; + } + public boolean isSecure(Socket socket) throws IllegalArgumentException { Assert.isNotNull(socket); if (!(socket instanceof SSLSocket)) { @@ -109,16 +112,4 @@ class PollingSslProtocolSocketFactory implements LayeredSchemeSocketFactory { return true; } - public Socket createLayeredSocket(Socket socket, String target, int port, boolean autoClose) throws IOException, - UnknownHostException { - return NetUtil.configureSocket(getSocketFactory().createSocket(socket, target, port, autoClose)); - } - - public SSLSocketFactory getSocketFactory() throws IOException { - if (socketFactory == null) { - throw new IOException("Could not initialize SSL context"); //$NON-NLS-1$ - } - return socketFactory; - } - } |

