Skip to content

Commit

Permalink
Merge pull request #7469 from acdemyers/7456-verifyHostname
Browse files Browse the repository at this point in the history
Hostname verification support on ssl configuration
  • Loading branch information
acdemyers authored May 17, 2019
2 parents 36b60fc + 251a11e commit 5f2ef3e
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 49 deletions.
2 changes: 1 addition & 1 deletion dev/com.ibm.websphere.appserver.api.ssl/bnd.bnd
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# IBM Corporation - initial API and implementation
#*******************************************************************************
-include= ~../cnf/resources/bnd/bundle.props
bVersion: 1.1
bVersion: 1.2

Bundle-Name: WebSphere SSL API
Bundle-Description: WebSphere SSL API, version ${bVersion}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Subsystem-Name: Secure Socket Layer 1.0
com.ibm.ws.crypto.certificateutil
-jars=com.ibm.websphere.appserver.spi.ssl; location:=dev/spi/ibm/, \
com.ibm.websphere.appserver.api.ssl; location:=dev/api/ibm/
-files=dev/spi/ibm/javadoc/com.ibm.websphere.appserver.spi.ssl_1.2-javadoc.zip, \
dev/api/ibm/javadoc/com.ibm.websphere.appserver.api.ssl_1.1-javadoc.zip
-files=dev/spi/ibm/javadoc/com.ibm.websphere.appserver.spi.ssl_1.3-javadoc.zip, \
dev/api/ibm/javadoc/com.ibm.websphere.appserver.api.ssl_1.2-javadoc.zip
kind=ga
edition=core
superseded-by=transportSecurity-1.0
2 changes: 1 addition & 1 deletion dev/com.ibm.websphere.appserver.spi.ssl/bnd.bnd
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# IBM Corporation - initial API and implementation
#*******************************************************************************
-include= ~../cnf/resources/bnd/bundle.props
bVersion: 1.2
bVersion: 1.3

Bundle-Name: WebSphere SSL SPI
Bundle-Description: WebSphere SSL SPI, version ${bVersion}
Expand Down
2 changes: 1 addition & 1 deletion dev/com.ibm.ws.ssl/bnd.bnd
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# IBM Corporation - initial API and implementation
#*******************************************************************************
-include= ~../cnf/resources/bnd/bundle.props
bVersion=1.1
bVersion=1.2

Bundle-Name: SSL Configuration
Bundle-SymbolicName: com.ibm.ws.ssl; singleton:=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ repertiore.HIGH=Cipher suites 3DES and 128 bit and higher
repertiore.MEDIUM=Cipher suites DES and 40 bit
repertiore.LOW=Cipher suites without encryption
repertiore.CUSTOM=Custom list of cipher suites
repertoire.verifyHostname=Host name verification
repertoire.verifyHostname.desc=Specifies whether host name verification for outbound connections using a specific SSL configuration is enabled. If set to true, then all outbound SSL connections that use the specified SSL configuration undergo verification of the target server host name against that server's certificate. The attribute is set to false by default.

keystore.config=Keystore
keystore.config.desc=A repository of security certificates used for SSL encryption.
Expand Down
3 changes: 3 additions & 0 deletions dev/com.ibm.ws.ssl/resources/OSGI-INF/metatype/metatype.xml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@

<AD id="outboundConnection" ibm:flat="true" ibm:type="pid" ibm:reference="com.ibm.ws.ssl.repertoire.config.outboundConnection"
required="false" type="String" cardinality="2147483647" />

<AD id="verifyHostname" name="%repertoire.verifyHostname" description="%repertoire.verifyHostname.desc"
required="false" type="Boolean" default="false" />

</OCD>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ private Constants() {
public static final String SSLPROP_DEFAULT_ALIAS = "com.ibm.ssl.defaultAlias";
public static final String SSLPROP_URL_HOSTNAME_VERIFICATION = "com.ibm.ssl.performURLHostNameVerification";
public static final String SSLPROP_SKIP_DEFAULT_TM_WHEN_CUSTOM_TM_DEFINED = "com.ibm.ssl.skipDefaultTrustManagerWhenCustomDefined";
public static final String SSLPROP_HOSTNAME_VERIFICATION = "com.ibm.ws.ssl.verifyHostname";

public static final String SSLPROP_AUTOACCEPT_SERVER_CERT = "com.ibm.ssl.autoaccept.server.certificates";
public static final String SSLPROP_AUTOSTORE_SERVER_CERT = "com.ibm.ssl.autostore.server.certificates";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010 IBM Corporation and others.
* Copyright (c) 2010, 2019 IBM Corporation 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
Expand All @@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
/**
* @version 1.2
* @version 1.3
*/
@org.osgi.annotation.versioning.Version("1.2")
@org.osgi.annotation.versioning.Version("1.3")
package com.ibm.websphere.ssl;
53 changes: 22 additions & 31 deletions dev/com.ibm.ws.ssl/src/com/ibm/ws/ssl/config/SSLConfigManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,11 @@ private SSLConfig parseSecureSocketLayer(Map<String, Object> map, boolean reinit
sslprops.setProperty(Constants.SSLPROP_ALIAS, prop);
}

Boolean hostnameVerification = (Boolean) map.get("verifyHostname");
if (null != hostnameVerification) {
sslprops.setProperty(Constants.SSLPROP_HOSTNAME_VERIFICATION, hostnameVerification.toString());
}

if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
Tr.debug(tc, "Saving SSLConfig: " + sslprops);

Expand Down Expand Up @@ -1586,49 +1591,35 @@ public synchronized boolean isClientAuthenticationEnabled() {
* @param socket
* @return
*/
public SSLSocket setCipherListOnSocket(java.util.Properties props, javax.net.ssl.SSLSocket socket) {
public String[] getCipherList(java.util.Properties props, SSLSocket socket) {
if (tc.isEntryEnabled())
Tr.entry(tc, "setCipherListOnSocket");

if (props == null) {
if (tc.isEntryEnabled())
Tr.exit(tc, "setCipherListOnSocket props == null");
return socket;
}
Tr.entry(tc, "getCipherList");

String ciphers[] = null;
String cipherString = props.getProperty(Constants.SSLPROP_ENABLED_CIPHERS);

if (socket != null) {

try {

if (cipherString != null) {
try {

ciphers = cipherString.split("\\s");
} else {
String securityLevel = props.getProperty(Constants.SSLPROP_SECURITY_LEVEL);
if (tc.isDebugEnabled())
Tr.debug(tc, "securityLevel from properties is " + securityLevel);
if (securityLevel == null)
securityLevel = "HIGH";
if (cipherString != null) {

String[] supportedCiphers = socket.getEnabledCipherSuites();
ciphers = com.ibm.ws.ssl.config.SSLConfigManager.getInstance().adjustSupportedCiphersToSecurityLevel(supportedCiphers, securityLevel);
ciphers = cipherString.split("\\s");
} else {
String securityLevel = props.getProperty(Constants.SSLPROP_SECURITY_LEVEL);
if (tc.isDebugEnabled())
Tr.debug(tc, "securityLevel from properties is " + securityLevel);
if (securityLevel == null)
securityLevel = "HIGH";

}
if (ciphers != null) {
socket.setEnabledCipherSuites(ciphers);
}
ciphers = adjustSupportedCiphersToSecurityLevel(socket.getEnabledCipherSuites(), securityLevel);

} catch (Exception e) {
if (tc.isDebugEnabled())
Tr.debug(tc, "Exception setting ciphers in SSL Socket Factory.", new Object[] { e });
}
} catch (Exception e) {
if (tc.isDebugEnabled())
Tr.debug(tc, "Exception setting ciphers in SSL Socket Factory.", new Object[] { e });
}
if (tc.isEntryEnabled())
Tr.exit(tc, "setCipherListOnSocket");
return socket;
Tr.exit(tc, "getCipherList");
return ciphers;
}

public boolean isTransportSecurityEnabled() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 IBM Corporation and others.
* Copyright (c) 2017, 2019 IBM Corporation 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
Expand All @@ -20,8 +20,11 @@
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.net.SocketFactory;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import com.ibm.ejs.ras.Tr;
Expand Down Expand Up @@ -49,6 +52,8 @@ public class LibertySSLSocketFactory extends javax.net.ssl.SSLSocketFactory {
protected boolean default_constructor = true;
private static com.ibm.ws.ssl.protocol.LibertySSLSocketFactory thisClass = null;

private static String ENDPOINT_ALGORITHM = "HTTPS";

/***
* <p>
* This is the default constructor which will retrieve the default SSL configuration
Expand Down Expand Up @@ -266,7 +271,7 @@ public java.net.Socket createSocket() throws IOException {
Tr.entry(tc, "createSocket");
javax.net.ssl.SSLSocketFactory currentFactory = default_factory;
javax.net.ssl.SSLSocket socket = null;
java.util.Properties sslProps = props;
java.util.Properties sslprops = props;
if (default_constructor) {
try {
java.util.Properties sslPropsOnThread = getSSLPropertiesOnThread();
Expand All @@ -278,10 +283,10 @@ public java.net.Socket createSocket() throws IOException {
currentConnectionInfo = new HashMap<String, Object>();
currentConnectionInfo.put(Constants.CONNECTION_INFO_DIRECTION, Constants.DIRECTION_OUTBOUND);
}
sslProps = getProperties(null, currentConnectionInfo, null);
sslprops = getProperties(null, currentConnectionInfo, null);
if (tc.isDebugEnabled())
Tr.debug(tc, "Getting SSLSocketFactory");
currentFactory = getSSLSocketFactory(currentConnectionInfo, sslProps);
currentFactory = getSSLSocketFactory(currentConnectionInfo, sslprops);
if (tc.isDebugEnabled())
Tr.debug(tc, "Got SSLSocketFactory", new Object[] { currentFactory });
} else {
Expand Down Expand Up @@ -311,7 +316,12 @@ public Object run() {
}
if (currentFactory != null) {
socket = (javax.net.ssl.SSLSocket) currentFactory.createSocket();
socket = SSLConfigManager.getInstance().setCipherListOnSocket(sslProps, socket);

SSLParameters p = socket.getSSLParameters();
String[] ciphers = SSLConfigManager.getInstance().getCipherList(sslprops, socket);
p.setCipherSuites(ciphers);

socket.setSSLParameters(p);
} else
throw new javax.net.ssl.SSLException("SSLSocketFactory is null. This can occur if javax.net.ssl.SSLSocketFactory.getDefault() is called to create a socket and javax.net.ssl.* properties are not set.");

Expand Down Expand Up @@ -365,7 +375,10 @@ public java.net.Socket createSocket(java.net.Socket s, String host, int port, bo

if (factory != null) {
socket = (javax.net.ssl.SSLSocket) factory.createSocket(s, host, port, autoClose);
socket = SSLConfigManager.getInstance().setCipherListOnSocket(sslprops, socket);

SSLParameters p = createSSLParameters(sslprops, socket);
socket.setSSLParameters(p);

} else
throw new javax.net.ssl.SSLException("SSLSocketFactory is null. This can occur if javax.net.ssl.SSLSocketFactory.getDefault() is called to create a socket and javax.net.ssl.* properties are not set.");
if (tc.isEntryEnabled())
Expand Down Expand Up @@ -441,7 +454,10 @@ public String run() {

if (factory != null) {
socket = (javax.net.ssl.SSLSocket) factory.createSocket(host, port);
socket = SSLConfigManager.getInstance().setCipherListOnSocket(sslprops, socket);

SSLParameters p = createSSLParameters(sslprops, socket);
socket.setSSLParameters(p);

} else
throw new javax.net.ssl.SSLException("SSLSocketFactory is null. This can occur if javax.net.ssl.SSLSocketFactory.getDefault() is called to create a socket and javax.net.ssl.* properties are not set.");

Expand Down Expand Up @@ -526,7 +542,10 @@ public String run() {

if (factory != null) {
socket = (javax.net.ssl.SSLSocket) factory.createSocket(address, port, localAddress, localPort);
socket = SSLConfigManager.getInstance().setCipherListOnSocket(sslprops, socket);

SSLParameters p = createSSLParameters(sslprops, socket);
socket.setSSLParameters(p);

} else
throw new javax.net.ssl.SSLException("SSLSocketFactory is null. This can occur if javax.net.ssl.SSLSocketFactory.getDefault() is called to create a socket and javax.net.ssl.* properties are not set.");

Expand Down Expand Up @@ -582,7 +601,11 @@ public java.net.Socket createSocket(String host, int port) throws IOException, U

if (factory != null) {
socket = (javax.net.ssl.SSLSocket) factory.createSocket(host, port);
socket = SSLConfigManager.getInstance().setCipherListOnSocket(sslprops, socket);

if (sslprops != null) {
SSLParameters p = createSSLParameters(sslprops, socket);
socket.setSSLParameters(p);
}
} else
throw new javax.net.ssl.SSLException("SSLSocketFactory is null. This can occur if javax.net.ssl.SSLSocketFactory.getDefault() is called to create a socket and javax.net.ssl.* properties are not set.");

Expand Down Expand Up @@ -639,7 +662,12 @@ public java.net.Socket createSocket(String host, int port, InetAddress localHost

if (factory != null) {
socket = (javax.net.ssl.SSLSocket) factory.createSocket(host, port, localHost, localPort);
socket = SSLConfigManager.getInstance().setCipherListOnSocket(sslprops, socket);

if (sslprops != null) {
SSLParameters p = createSSLParameters(sslprops, socket);
socket.setSSLParameters(p);
}

} else
throw new javax.net.ssl.SSLException("SSLSocketFactory is null. This can occur if javax.net.ssl.SSLSocketFactory.getDefault() is called to create a socket and javax.net.ssl.* properties are not set.");

Expand Down Expand Up @@ -668,6 +696,22 @@ public int compare(SocketFactory sf1, SocketFactory sf2) {
}
}

private static SSLParameters createSSLParameters(Properties sslprops, SSLSocket socket) {

SSLParameters p = socket.getSSLParameters();
String[] ciphers = SSLConfigManager.getInstance().getCipherList(sslprops, socket);
p.setCipherSuites(ciphers);

//Enable hostname verification
String enableEndpointId = sslprops.getProperty(Constants.SSLPROP_HOSTNAME_VERIFICATION, "false");
if (enableEndpointId != null && enableEndpointId.equalsIgnoreCase("true")) {
p.setEndpointIdentificationAlgorithm(ENDPOINT_ALGORITHM);
}

return p;

}

/**
* Convenience method to call {@link JSSEHelper#getSSLPropertiesOnThread()} with elevated privileges.
*
Expand Down

0 comments on commit 5f2ef3e

Please sign in to comment.