Author: sebb Date: Mon Aug 24 00:24:36 2015 New Revision: 1697287 URL: http://svn.apache.org/r1697287 Log: NET-579 SSL/TLS SocketClients do not verify the hostname against the certificate
Added: commons/proper/net/trunk/src/main/java/org/apache/commons/net/util/SSLSocketUtils.java (with props) Modified: commons/proper/net/trunk/src/changes/changes.xml commons/proper/net/trunk/src/main/java/org/apache/commons/net/SocketClient.java commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/FTPSClient.java commons/proper/net/trunk/src/main/java/org/apache/commons/net/imap/IMAPSClient.java commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3SClient.java commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSClient.java Modified: commons/proper/net/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/changes/changes.xml?rev=1697287&r1=1697286&r2=1697287&view=diff ============================================================================== --- commons/proper/net/trunk/src/changes/changes.xml [utf-8] (original) +++ commons/proper/net/trunk/src/changes/changes.xml [utf-8] Mon Aug 24 00:24:36 2015 @@ -72,6 +72,9 @@ This is mainly a bug-fix release. See fu IMAPExportMbox (example app) allows IMAP folders to be exported into an mbox file. This is the inverse of the IMAPImportMbox example added previously "> + <action issue="NET-579" type="fix" dev="sebb" due-to="Simon Arlott"> + SSL/TLS SocketClients do not verify the hostname against the certificate + </action> <action issue="NET-576" type="update" dev="sebb"> Allow FTPClient to use SYST response if system type is not specified in configuration </action> Modified: commons/proper/net/trunk/src/main/java/org/apache/commons/net/SocketClient.java URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/SocketClient.java?rev=1697287&r1=1697286&r2=1697287&view=diff ============================================================================== --- commons/proper/net/trunk/src/main/java/org/apache/commons/net/SocketClient.java (original) +++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/SocketClient.java Mon Aug 24 00:24:36 2015 @@ -80,6 +80,9 @@ public abstract class SocketClient /** The socket used for the connection. */ protected Socket _socket_; + /** The hostname used for the connection (null = no hostname supplied). */ + protected String _hostname_; + /** The default port the client should connect to. */ protected int _defaultPort_; @@ -123,6 +126,7 @@ public abstract class SocketClient public SocketClient() { _socket_ = null; + _hostname_ = null; _input_ = null; _output_ = null; _timeout_ = 0; @@ -173,6 +177,7 @@ public abstract class SocketClient public void connect(InetAddress host, int port) throws SocketException, IOException { + _hostname_ = null; _socket_ = _socketFactory_.createSocket(); if (receiveBufferSize != -1) { _socket_.setReceiveBufferSize(receiveBufferSize); @@ -202,6 +207,7 @@ public abstract class SocketClient throws SocketException, IOException { connect(InetAddress.getByName(hostname), port); + _hostname_ = hostname; } @@ -224,6 +230,7 @@ public abstract class SocketClient InetAddress localAddr, int localPort) throws SocketException, IOException { + _hostname_ = null; _socket_ = _socketFactory_.createSocket(); if (receiveBufferSize != -1) { _socket_.setReceiveBufferSize(receiveBufferSize); @@ -258,6 +265,7 @@ public abstract class SocketClient throws SocketException, IOException { connect(InetAddress.getByName(hostname), port, localAddr, localPort); + _hostname_ = hostname; } @@ -275,6 +283,7 @@ public abstract class SocketClient */ public void connect(InetAddress host) throws SocketException, IOException { + _hostname_ = null; connect(host, _defaultPort_); } @@ -295,6 +304,7 @@ public abstract class SocketClient public void connect(String hostname) throws SocketException, IOException { connect(hostname, _defaultPort_); + _hostname_ = hostname; } @@ -314,6 +324,7 @@ public abstract class SocketClient closeQuietly(_input_); closeQuietly(_output_); _socket_ = null; + _hostname_ = null; _input_ = null; _output_ = null; } Modified: commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/FTPSClient.java URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/FTPSClient.java?rev=1697287&r1=1697286&r2=1697287&view=diff ============================================================================== --- commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/FTPSClient.java (original) +++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/ftp/FTPSClient.java Mon Aug 24 00:24:36 2015 @@ -23,21 +23,28 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; + +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import org.apache.commons.net.util.Base64; import org.apache.commons.net.util.SSLContextUtils; +import org.apache.commons.net.util.SSLSocketUtils; import org.apache.commons.net.util.TrustManagerUtils; /** * FTP over SSL processing. If desired, the JVM property -Djavax.net.debug=all can be used to * see wire-level SSL details. * + * Warning: the hostname is not verified against the certificate by default, use + * {@link #setHostnameVerifier(HostnameVerifier)} or {@link #setEndpointCheckingEnabled(boolean)} + * (on Java 1.7+) to enable verification. Verification is only performed on client mode connections. * @version $Id$ * @since 2.0 */ @@ -106,6 +113,12 @@ public class FTPSClient extends FTPClien /** The {@link KeyManager}, default null (i.e. use system default). */ private KeyManager keyManager = null; + /** The {@link HostnameVerifier} to use post-TLS, default null (i.e. no verification). */ + private HostnameVerifier hostnameVerifier = null; + + /** Use Java 1.7+ HTTPS Endpoint Identification Algorithim. */ + private boolean tlsEndpointChecking; + /** * Constructor for FTPSClient, calls {@link #FTPSClient(String, boolean)}. * @@ -248,14 +261,19 @@ public class FTPSClient extends FTPClien initSslContext(); SSLSocketFactory ssf = context.getSocketFactory(); - String ip = _socket_.getInetAddress().getHostAddress(); + String host = (_hostname_ != null) ? _hostname_ : getRemoteAddress().getHostAddress(); int port = _socket_.getPort(); SSLSocket socket = - (SSLSocket) ssf.createSocket(_socket_, ip, port, false); + (SSLSocket) ssf.createSocket(_socket_, host, port, false); socket.setEnableSessionCreation(isCreation); socket.setUseClientMode(isClientMode); - // server mode - if (!isClientMode) { + + // client mode + if (isClientMode) { + if (tlsEndpointChecking) { + SSLSocketUtils.enableEndpointNameVerification(socket); + } + } else { // server mode socket.setNeedClientAuth(isNeedClientAuth); socket.setWantClientAuth(isWantClientAuth); } @@ -274,6 +292,12 @@ public class FTPSClient extends FTPClien socket .getInputStream(), getControlEncoding())); _controlOutput_ = new BufferedWriter(new OutputStreamWriter( socket.getOutputStream(), getControlEncoding())); + + if (isClientMode) { + if (hostnameVerifier != null && !hostnameVerifier.verify(host, socket.getSession())) { + throw new SSLHandshakeException("Hostname doesn't match certificate"); + } + } } /** @@ -658,6 +682,56 @@ public class FTPSClient extends FTPClien } /** + * Get the currently configured {@link HostnameVerifier}. + * The verifier is only used on client mode connections. + * @return A HostnameVerifier instance. + * @since 3.4 + */ + public HostnameVerifier getHostnameVerifier() + { + return hostnameVerifier; + } + + /** + * Override the default {@link HostnameVerifier} to use. + * The verifier is only used on client mode connections. + * @param newHostnameVerifier The HostnameVerifier implementation to set or <code>null</code> to disable. + * @since 3.4 + */ + public void setHostnameVerifier(HostnameVerifier newHostnameVerifier) + { + hostnameVerifier = newHostnameVerifier; + } + + /** + * Return whether or not endpoint identification using the HTTPS algorithm + * on Java 1.7+ is enabled. The default behaviour is for this to be disabled. + * + * This check is only performed on client mode connections. + * + * @return True if enabled, false if not. + * @since 3.4 + */ + public boolean isEndpointCheckingEnabled() + { + return tlsEndpointChecking; + } + + /** + * Automatic endpoint identification checking using the HTTPS algorithm + * is supported on Java 1.7+. The default behaviour is for this to be disabled. + * + * This check is only performed on client mode connections. + * + * @param enable Enable automatic endpoint identification checking using the HTTPS algorithm on Java 1.7+. + * @since 3.4 + */ + public void setEndpointCheckingEnabled(boolean enable) + { + tlsEndpointChecking = enable; + } + + /** * Closes the connection to the FTP server and restores * connection parameters to the default values. * <p> Modified: commons/proper/net/trunk/src/main/java/org/apache/commons/net/imap/IMAPSClient.java URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/imap/IMAPSClient.java?rev=1697287&r1=1697286&r2=1697287&view=diff ============================================================================== --- commons/proper/net/trunk/src/main/java/org/apache/commons/net/imap/IMAPSClient.java (original) +++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/imap/IMAPSClient.java Mon Aug 24 00:24:36 2015 @@ -22,15 +22,18 @@ import java.io.InputStreamReader; import java.io.IOException; import java.io.OutputStreamWriter; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import org.apache.commons.net.io.CRLFLineReader; import org.apache.commons.net.util.SSLContextUtils; +import org.apache.commons.net.util.SSLSocketUtils; /** * The IMAPSClient class provides SSL/TLS connection encryption to IMAPClient. @@ -45,6 +48,10 @@ import org.apache.commons.net.util.SSLCo * IMAPSClient c = new IMAPSClient(); * c.connect("127.0.0.1", 143); * if (c.execTLS()) { /rest of the commands here/ } + * + * Warning: the hostname is not verified against the certificate by default, use + * {@link #setHostnameVerifier(HostnameVerifier)} or {@link #setEndpointCheckingEnabled(boolean)} + * (on Java 1.7+) to enable verification. */ public class IMAPSClient extends IMAPClient { @@ -73,6 +80,12 @@ public class IMAPSClient extends IMAPCli /** The {@link KeyManager}, default null. */ private KeyManager keyManager = null; + /** The {@link HostnameVerifier} to use post-TLS, default null (i.e. no verification). */ + private HostnameVerifier hostnameVerifier = null; + + /** Use Java 1.7+ HTTPS Endpoint Identification Algorithim. */ + private boolean tlsEndpointChecking; + /** * Constructor for IMAPSClient. * Sets security mode to explicit (isImplicit = false). @@ -185,13 +198,17 @@ public class IMAPSClient extends IMAPCli initSSLContext(); SSLSocketFactory ssf = context.getSocketFactory(); - String ip = getRemoteAddress().getHostAddress(); + String host = (_hostname_ != null) ? _hostname_ : getRemoteAddress().getHostAddress(); int port = getRemotePort(); SSLSocket socket = - (SSLSocket) ssf.createSocket(_socket_, ip, port, true); + (SSLSocket) ssf.createSocket(_socket_, host, port, true); socket.setEnableSessionCreation(true); socket.setUseClientMode(true); + if (tlsEndpointChecking) { + SSLSocketUtils.enableEndpointNameVerification(socket); + } + if (protocols != null) { socket.setEnabledProtocols(protocols); } @@ -210,6 +227,10 @@ public class IMAPSClient extends IMAPCli __writer = new BufferedWriter(new OutputStreamWriter(_output_, __DEFAULT_ENCODING)); + + if (hostnameVerifier != null && !hostnameVerifier.verify(host, socket.getSession())) { + throw new SSLHandshakeException("Hostname doesn't match certificate"); + } } /** @@ -320,5 +341,48 @@ public class IMAPSClient extends IMAPCli trustManager = newTrustManager; } + /** + * Get the currently configured {@link HostnameVerifier}. + * @return A HostnameVerifier instance. + * @since 3.4 + */ + public HostnameVerifier getHostnameVerifier() + { + return hostnameVerifier; + } + + /** + * Override the default {@link HostnameVerifier} to use. + * @param newHostnameVerifier The HostnameVerifier implementation to set or <code>null</code> to disable. + * @since 3.4 + */ + public void setHostnameVerifier(HostnameVerifier newHostnameVerifier) + { + hostnameVerifier = newHostnameVerifier; + } + + /** + * Return whether or not endpoint identification using the HTTPS algorithm + * on Java 1.7+ is enabled. The default behaviour is for this to be disabled. + * + * @return True if enabled, false if not. + * @since 3.4 + */ + public boolean isEndpointCheckingEnabled() + { + return tlsEndpointChecking; + } + + /** + * Automatic endpoint identification checking using the HTTPS algorithm + * is supported on Java 1.7+. The default behaviour is for this to be disabled. + * + * @param enable Enable automatic endpoint identification checking using the HTTPS algorithm on Java 1.7+. + * @since 3.4 + */ + public void setEndpointCheckingEnabled(boolean enable) + { + tlsEndpointChecking = enable; + } } /* kate: indent-width 4; replace-tabs on; */ Modified: commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3SClient.java URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3SClient.java?rev=1697287&r1=1697286&r2=1697287&view=diff ============================================================================== --- commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3SClient.java (original) +++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/pop3/POP3SClient.java Mon Aug 24 00:24:36 2015 @@ -22,15 +22,18 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import org.apache.commons.net.io.CRLFLineReader; import org.apache.commons.net.util.SSLContextUtils; +import org.apache.commons.net.util.SSLSocketUtils; /** * POP3 over SSL processing. Copied from FTPSClient.java and modified to suit POP3. @@ -44,6 +47,10 @@ import org.apache.commons.net.util.SSLCo * POP3SClient c = new POP3SClient(); * c.connect("127.0.0.1", 110); * if (c.execTLS()) { /rest of the commands here/ } + * + * Warning: the hostname is not verified against the certificate by default, use + * {@link #setHostnameVerifier(HostnameVerifier)} or {@link #setEndpointCheckingEnabled(boolean)} + * (on Java 1.7+) to enable verification. * @since 3.0 */ public class POP3SClient extends POP3Client @@ -77,6 +84,12 @@ public class POP3SClient extends POP3Cli /** The {@link KeyManager}, default null. */ private KeyManager keyManager = null; + /** The {@link HostnameVerifier} to use post-TLS, default null (i.e. no verification). */ + private HostnameVerifier hostnameVerifier = null; + + /** Use Java 1.7+ HTTPS Endpoint Identification Algorithim. */ + private boolean tlsEndpointChecking; + /** * Constructor for POP3SClient, using {@link #DEFAULT_PROTOCOL} i.e. TLS * Sets security mode to explicit. @@ -194,13 +207,17 @@ public class POP3SClient extends POP3Cli initSSLContext(); SSLSocketFactory ssf = context.getSocketFactory(); - String ip = getRemoteAddress().getHostAddress(); + String host = (_hostname_ != null) ? _hostname_ : getRemoteAddress().getHostAddress(); int port = getRemotePort(); SSLSocket socket = - (SSLSocket) ssf.createSocket(_socket_, ip, port, true); + (SSLSocket) ssf.createSocket(_socket_, host, port, true); socket.setEnableSessionCreation(true); socket.setUseClientMode(true); + if (tlsEndpointChecking) { + SSLSocketUtils.enableEndpointNameVerification(socket); + } + if (protocols != null) { socket.setEnabledProtocols(protocols); } @@ -215,6 +232,10 @@ public class POP3SClient extends POP3Cli _output_ = socket.getOutputStream(); _reader = new CRLFLineReader(new InputStreamReader(_input_, _DEFAULT_ENCODING)); _writer = new BufferedWriter(new OutputStreamWriter(_output_, _DEFAULT_ENCODING)); + + if (hostnameVerifier != null && !hostnameVerifier.verify(host, socket.getSession())) { + throw new SSLHandshakeException("Hostname doesn't match certificate"); + } } /** @@ -324,6 +345,50 @@ public class POP3SClient extends POP3Cli { trustManager = newTrustManager; } + + /** + * Get the currently configured {@link HostnameVerifier}. + * @return A HostnameVerifier instance. + * @since 3.4 + */ + public HostnameVerifier getHostnameVerifier() + { + return hostnameVerifier; + } + + /** + * Override the default {@link HostnameVerifier} to use. + * @param newHostnameVerifier The HostnameVerifier implementation to set or <code>null</code> to disable. + * @since 3.4 + */ + public void setHostnameVerifier(HostnameVerifier newHostnameVerifier) + { + hostnameVerifier = newHostnameVerifier; + } + + /** + * Return whether or not endpoint identification using the HTTPS algorithm + * on Java 1.7+ is enabled. The default behaviour is for this to be disabled. + * + * @return True if enabled, false if not. + * @since 3.4 + */ + public boolean isEndpointCheckingEnabled() + { + return tlsEndpointChecking; + } + + /** + * Automatic endpoint identification checking using the HTTPS algorithm + * is supported on Java 1.7+. The default behaviour is for this to be disabled. + * + * @param enable Enable automatic endpoint identification checking using the HTTPS algorithm on Java 1.7+. + * @since 3.4 + */ + public void setEndpointCheckingEnabled(boolean enable) + { + tlsEndpointChecking = enable; + } } /* kate: indent-width 4; replace-tabs on; */ Modified: commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSClient.java URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSClient.java?rev=1697287&r1=1697286&r2=1697287&view=diff ============================================================================== --- commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSClient.java (original) +++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/smtp/SMTPSClient.java Mon Aug 24 00:24:36 2015 @@ -22,14 +22,17 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import org.apache.commons.net.io.CRLFLineReader; import org.apache.commons.net.util.SSLContextUtils; +import org.apache.commons.net.util.SSLSocketUtils; /** * SMTP over SSL processing. Copied from FTPSClient.java and modified to suit SMTP. @@ -43,6 +46,10 @@ import org.apache.commons.net.util.SSLCo * SMTPSClient c = new SMTPSClient(); * c.connect("127.0.0.1", 25); * if (c.execTLS()) { /rest of the commands here/ } + * + * Warning: the hostname is not verified against the certificate by default, use + * {@link #setHostnameVerifier(HostnameVerifier)} or {@link #setEndpointCheckingEnabled(boolean)} + * (on Java 1.7+) to enable verification. * @since 3.0 */ public class SMTPSClient extends SMTPClient @@ -68,6 +75,12 @@ public class SMTPSClient extends SMTPCli /** The {@link KeyManager}, default null (i.e. use system managers). */ private KeyManager keyManager = null; // seems not to be required + /** The {@link HostnameVerifier} to use post-TLS, default null (i.e. no verification). */ + private HostnameVerifier hostnameVerifier = null; + + /** Use Java 1.7+ HTTPS Endpoint Identification Algorithim. */ + private boolean tlsEndpointChecking; + /** * Constructor for SMTPSClient, using {@link #DEFAULT_PROTOCOL} i.e. TLS * Sets security mode to explicit (isImplicit = false). @@ -183,13 +196,16 @@ public class SMTPSClient extends SMTPCli initSSLContext(); SSLSocketFactory ssf = context.getSocketFactory(); - String ip = getRemoteAddress().getHostAddress(); + String host = (_hostname_ != null) ? _hostname_ : getRemoteAddress().getHostAddress(); int port = getRemotePort(); SSLSocket socket = - (SSLSocket) ssf.createSocket(_socket_, ip, port, true); + (SSLSocket) ssf.createSocket(_socket_, host, port, true); socket.setEnableSessionCreation(true); socket.setUseClientMode(true); + if (tlsEndpointChecking) { + SSLSocketUtils.enableEndpointNameVerification(socket); + } if (protocols != null) { socket.setEnabledProtocols(protocols); } @@ -207,6 +223,9 @@ public class SMTPSClient extends SMTPCli _writer = new BufferedWriter( new OutputStreamWriter(_output_, encoding)); + if (hostnameVerifier != null && !hostnameVerifier.verify(host, socket.getSession())) { + throw new SSLHandshakeException("Hostname doesn't match certificate"); + } } /** @@ -315,6 +334,50 @@ public class SMTPSClient extends SMTPCli { trustManager = newTrustManager; } + + /** + * Get the currently configured {@link HostnameVerifier}. + * @return A HostnameVerifier instance. + * @since 3.4 + */ + public HostnameVerifier getHostnameVerifier() + { + return hostnameVerifier; + } + + /** + * Override the default {@link HostnameVerifier} to use. + * @param newHostnameVerifier The HostnameVerifier implementation to set or <code>null</code> to disable. + * @since 3.4 + */ + public void setHostnameVerifier(HostnameVerifier newHostnameVerifier) + { + hostnameVerifier = newHostnameVerifier; + } + + /** + * Return whether or not endpoint identification using the HTTPS algorithm + * on Java 1.7+ is enabled. The default behaviour is for this to be disabled. + * + * @return True if enabled, false if not. + * @since 3.4 + */ + public boolean isEndpointCheckingEnabled() + { + return tlsEndpointChecking; + } + + /** + * Automatic endpoint identification checking using the HTTPS algorithm + * is supported on Java 1.7+. The default behaviour is for this to be disabled. + * + * @param enable Enable automatic endpoint identification checking using the HTTPS algorithm on Java 1.7+. + * @since 3.4 + */ + public void setEndpointCheckingEnabled(boolean enable) + { + tlsEndpointChecking = enable; + } } /* kate: indent-width 4; replace-tabs on; */ Added: commons/proper/net/trunk/src/main/java/org/apache/commons/net/util/SSLSocketUtils.java URL: http://svn.apache.org/viewvc/commons/proper/net/trunk/src/main/java/org/apache/commons/net/util/SSLSocketUtils.java?rev=1697287&view=auto ============================================================================== --- commons/proper/net/trunk/src/main/java/org/apache/commons/net/util/SSLSocketUtils.java (added) +++ commons/proper/net/trunk/src/main/java/org/apache/commons/net/util/SSLSocketUtils.java Mon Aug 24 00:24:36 2015 @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.commons.net.util; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.net.ssl.SSLSocket; + +/** + * General utilities for SSLSocket. + * @since 3.4 + */ +public class SSLSocketUtils { + private SSLSocketUtils() { + // Not instantiable + } + + /** + * Enable the HTTPS endpoint identification algorithm on an SSLSocket. + * @param socket the SSL socket + * @return {@code true} on success (this is only supported on Java 1.7+) + */ + public static boolean enableEndpointNameVerification(SSLSocket socket) { + try { + Class<?> cls = Class.forName("javax.net.ssl.SSLParameters"); + Method setEndpointIdentificationAlgorithm = cls.getDeclaredMethod("setEndpointIdentificationAlgorithm", String.class); + Method getSSLParameters = SSLSocket.class.getDeclaredMethod("getSSLParameters"); + Method setSSLParameters = SSLSocket.class.getDeclaredMethod("setSSLParameters", cls); + if (setEndpointIdentificationAlgorithm != null && getSSLParameters != null && setSSLParameters != null) { + Object sslParams = getSSLParameters.invoke(socket); + if (sslParams != null) { + setEndpointIdentificationAlgorithm.invoke(sslParams, "HTTPS"); + setSSLParameters.invoke(socket, sslParams); + return true; + } + } + } catch (SecurityException e) { + } catch (ClassNotFoundException e) { + } catch (NoSuchMethodException e) { + } catch (IllegalArgumentException e) { + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) { + } + return false; + } +} Propchange: commons/proper/net/trunk/src/main/java/org/apache/commons/net/util/SSLSocketUtils.java ------------------------------------------------------------------------------ svn:eol-style = native