OpenSslEngine.getSupportedCipherSuites() must return java names as well.
Motivation: At the moment OpenSslEngine.getSupportedCipherSuites() only return the original openssl cipher names and not the java names. We need also include the java names. Modifications: Correctly return the java names as well. Result: Correct implementation of OpenSslEngine.getSupportedCipherSuites()
This commit is contained in:
parent
278c36af0c
commit
7c1374dd54
@ -27,7 +27,9 @@ import org.apache.tomcat.jni.Pool;
|
|||||||
import org.apache.tomcat.jni.SSL;
|
import org.apache.tomcat.jni.SSL;
|
||||||
import org.apache.tomcat.jni.SSLContext;
|
import org.apache.tomcat.jni.SSLContext;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -43,7 +45,28 @@ public final class OpenSsl {
|
|||||||
private static final String UNKNOWN = "unknown";
|
private static final String UNKNOWN = "unknown";
|
||||||
private static final Throwable UNAVAILABILITY_CAUSE;
|
private static final Throwable UNAVAILABILITY_CAUSE;
|
||||||
|
|
||||||
private static final Set<String> AVAILABLE_CIPHER_SUITES;
|
static final Set<String> AVAILABLE_CIPHER_SUITES;
|
||||||
|
private static final Set<String> AVAILABLE_OPENSSL_CIPHER_SUITES;
|
||||||
|
private static final Set<String> AVAILABLE_JAVA_CIPHER_SUITES;
|
||||||
|
|
||||||
|
// Protocols
|
||||||
|
static final String PROTOCOL_SSL_V2_HELLO = "SSLv2Hello";
|
||||||
|
static final String PROTOCOL_SSL_V2 = "SSLv2";
|
||||||
|
static final String PROTOCOL_SSL_V3 = "SSLv3";
|
||||||
|
static final String PROTOCOL_TLS_V1 = "TLSv1";
|
||||||
|
static final String PROTOCOL_TLS_V1_1 = "TLSv1.1";
|
||||||
|
static final String PROTOCOL_TLS_V1_2 = "TLSv1.2";
|
||||||
|
|
||||||
|
private static final String[] SUPPORTED_PROTOCOLS = {
|
||||||
|
PROTOCOL_SSL_V2_HELLO,
|
||||||
|
PROTOCOL_SSL_V2,
|
||||||
|
PROTOCOL_SSL_V3,
|
||||||
|
PROTOCOL_TLS_V1,
|
||||||
|
PROTOCOL_TLS_V1_1,
|
||||||
|
PROTOCOL_TLS_V1_2
|
||||||
|
};
|
||||||
|
static final Set<String> SUPPORTED_PROTOCOLS_SET = Collections.unmodifiableSet(
|
||||||
|
new HashSet<String>(Arrays.asList(SUPPORTED_PROTOCOLS)));
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Throwable cause = null;
|
Throwable cause = null;
|
||||||
@ -93,7 +116,7 @@ public final class OpenSsl {
|
|||||||
UNAVAILABILITY_CAUSE = cause;
|
UNAVAILABILITY_CAUSE = cause;
|
||||||
|
|
||||||
if (cause == null) {
|
if (cause == null) {
|
||||||
final Set<String> availableCipherSuites = new LinkedHashSet<String>(128);
|
final Set<String> availableOpenSslCipherSuites = new LinkedHashSet<String>(128);
|
||||||
final long aprPool = Pool.create(0);
|
final long aprPool = Pool.create(0);
|
||||||
try {
|
try {
|
||||||
final long sslCtx = SSLContext.make(aprPool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
|
final long sslCtx = SSLContext.make(aprPool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
|
||||||
@ -104,10 +127,10 @@ public final class OpenSsl {
|
|||||||
try {
|
try {
|
||||||
for (String c: SSL.getCiphers(ssl)) {
|
for (String c: SSL.getCiphers(ssl)) {
|
||||||
// Filter out bad input.
|
// Filter out bad input.
|
||||||
if (c == null || c.length() == 0 || availableCipherSuites.contains(c)) {
|
if (c == null || c.length() == 0 || availableOpenSslCipherSuites.contains(c)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
availableCipherSuites.add(c);
|
availableOpenSslCipherSuites.add(c);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
SSL.freeSSL(ssl);
|
SSL.freeSSL(ssl);
|
||||||
@ -120,9 +143,29 @@ public final class OpenSsl {
|
|||||||
} finally {
|
} finally {
|
||||||
Pool.destroy(aprPool);
|
Pool.destroy(aprPool);
|
||||||
}
|
}
|
||||||
|
AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.unmodifiableSet(availableOpenSslCipherSuites);
|
||||||
|
|
||||||
AVAILABLE_CIPHER_SUITES = Collections.unmodifiableSet(availableCipherSuites);
|
final Set<String> availableJavaCipherSuites = new LinkedHashSet<String>(
|
||||||
|
AVAILABLE_OPENSSL_CIPHER_SUITES.size() * 2);
|
||||||
|
for (String cipher: AVAILABLE_OPENSSL_CIPHER_SUITES) {
|
||||||
|
// Included converted but also openssl cipher name
|
||||||
|
availableJavaCipherSuites.add(CipherSuiteConverter.toJava(cipher, "TLS"));
|
||||||
|
availableJavaCipherSuites.add(CipherSuiteConverter.toJava(cipher, "SSL"));
|
||||||
|
}
|
||||||
|
AVAILABLE_JAVA_CIPHER_SUITES = Collections.unmodifiableSet(availableJavaCipherSuites);
|
||||||
|
|
||||||
|
final Set<String> availableCipherSuites = new LinkedHashSet<String>(
|
||||||
|
AVAILABLE_OPENSSL_CIPHER_SUITES.size() + AVAILABLE_JAVA_CIPHER_SUITES.size());
|
||||||
|
for (String cipher: AVAILABLE_OPENSSL_CIPHER_SUITES) {
|
||||||
|
availableCipherSuites.add(cipher);
|
||||||
|
}
|
||||||
|
for (String cipher: AVAILABLE_JAVA_CIPHER_SUITES) {
|
||||||
|
availableCipherSuites.add(cipher);
|
||||||
|
}
|
||||||
|
AVAILABLE_CIPHER_SUITES = availableCipherSuites;
|
||||||
} else {
|
} else {
|
||||||
|
AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.emptySet();
|
||||||
|
AVAILABLE_JAVA_CIPHER_SUITES = Collections.emptySet();
|
||||||
AVAILABLE_CIPHER_SUITES = Collections.emptySet();
|
AVAILABLE_CIPHER_SUITES = Collections.emptySet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,12 +232,28 @@ public final class OpenSsl {
|
|||||||
return UNAVAILABILITY_CAUSE;
|
return UNAVAILABILITY_CAUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link #availableOpenSslCipherSuites()}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static Set<String> availableCipherSuites() {
|
||||||
|
return availableOpenSslCipherSuites();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the available OpenSSL cipher suites.
|
* Returns all the available OpenSSL cipher suites.
|
||||||
* Please note that the returned array may include the cipher suites that are insecure or non-functional.
|
* Please note that the returned array may include the cipher suites that are insecure or non-functional.
|
||||||
*/
|
*/
|
||||||
public static Set<String> availableCipherSuites() {
|
public static Set<String> availableOpenSslCipherSuites() {
|
||||||
return AVAILABLE_CIPHER_SUITES;
|
return AVAILABLE_OPENSSL_CIPHER_SUITES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the available cipher suites (Java-style).
|
||||||
|
* Please note that the returned array may include the cipher suites that are insecure or non-functional.
|
||||||
|
*/
|
||||||
|
public static Set<String> availableJavaCipherSuites() {
|
||||||
|
return AVAILABLE_JAVA_CIPHER_SUITES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -206,7 +265,7 @@ public final class OpenSsl {
|
|||||||
if (converted != null) {
|
if (converted != null) {
|
||||||
cipherSuite = converted;
|
cipherSuite = converted;
|
||||||
}
|
}
|
||||||
return AVAILABLE_CIPHER_SUITES.contains(cipherSuite);
|
return AVAILABLE_OPENSSL_CIPHER_SUITES.contains(cipherSuite);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isError(long errorCode) {
|
static boolean isError(long errorCode) {
|
||||||
|
@ -37,10 +37,8 @@ import java.security.cert.Certificate;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||||
|
|
||||||
import javax.net.ssl.SSLEngine;
|
import javax.net.ssl.SSLEngine;
|
||||||
@ -154,24 +152,6 @@ public final class OpenSslEngine extends SSLEngine {
|
|||||||
private static final int MAX_COMPRESSED_LENGTH = MAX_PLAINTEXT_LENGTH + 1024;
|
private static final int MAX_COMPRESSED_LENGTH = MAX_PLAINTEXT_LENGTH + 1024;
|
||||||
private static final int MAX_CIPHERTEXT_LENGTH = MAX_COMPRESSED_LENGTH + 1024;
|
private static final int MAX_CIPHERTEXT_LENGTH = MAX_COMPRESSED_LENGTH + 1024;
|
||||||
|
|
||||||
// Protocols
|
|
||||||
private static final String PROTOCOL_SSL_V2_HELLO = "SSLv2Hello";
|
|
||||||
private static final String PROTOCOL_SSL_V2 = "SSLv2";
|
|
||||||
private static final String PROTOCOL_SSL_V3 = "SSLv3";
|
|
||||||
private static final String PROTOCOL_TLS_V1 = "TLSv1";
|
|
||||||
private static final String PROTOCOL_TLS_V1_1 = "TLSv1.1";
|
|
||||||
private static final String PROTOCOL_TLS_V1_2 = "TLSv1.2";
|
|
||||||
|
|
||||||
private static final String[] SUPPORTED_PROTOCOLS = {
|
|
||||||
PROTOCOL_SSL_V2_HELLO,
|
|
||||||
PROTOCOL_SSL_V2,
|
|
||||||
PROTOCOL_SSL_V3,
|
|
||||||
PROTOCOL_TLS_V1,
|
|
||||||
PROTOCOL_TLS_V1_1,
|
|
||||||
PROTOCOL_TLS_V1_2
|
|
||||||
};
|
|
||||||
private static final Set<String> SUPPORTED_PROTOCOLS_SET = new HashSet<String>(Arrays.asList(SUPPORTED_PROTOCOLS));
|
|
||||||
|
|
||||||
// Header (5) + Data (2^14) + Compression (1024) + Encryption (1024) + MAC (20) + Padding (256)
|
// Header (5) + Data (2^14) + Compression (1024) + Encryption (1024) + MAC (20) + Padding (256)
|
||||||
static final int MAX_ENCRYPTED_PACKET_LENGTH = MAX_CIPHERTEXT_LENGTH + 5 + 20 + 256;
|
static final int MAX_ENCRYPTED_PACKET_LENGTH = MAX_CIPHERTEXT_LENGTH + 5 + 20 + 256;
|
||||||
|
|
||||||
@ -1038,8 +1018,7 @@ public final class OpenSslEngine extends SSLEngine {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getSupportedCipherSuites() {
|
public String[] getSupportedCipherSuites() {
|
||||||
Set<String> availableCipherSuites = OpenSsl.availableCipherSuites();
|
return OpenSsl.AVAILABLE_CIPHER_SUITES.toArray(new String[OpenSsl.AVAILABLE_CIPHER_SUITES.size()]);
|
||||||
return availableCipherSuites.toArray(new String[availableCipherSuites.size()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1110,14 +1089,14 @@ public final class OpenSslEngine extends SSLEngine {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getSupportedProtocols() {
|
public String[] getSupportedProtocols() {
|
||||||
return SUPPORTED_PROTOCOLS.clone();
|
return OpenSsl.SUPPORTED_PROTOCOLS_SET.toArray(new String[OpenSsl.SUPPORTED_PROTOCOLS_SET.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getEnabledProtocols() {
|
public String[] getEnabledProtocols() {
|
||||||
List<String> enabled = InternalThreadLocalMap.get().arrayList();
|
List<String> enabled = InternalThreadLocalMap.get().arrayList();
|
||||||
// Seems like there is no way to explict disable SSLv2Hello in openssl so it is always enabled
|
// Seems like there is no way to explict disable SSLv2Hello in openssl so it is always enabled
|
||||||
enabled.add(PROTOCOL_SSL_V2_HELLO);
|
enabled.add(OpenSsl.PROTOCOL_SSL_V2_HELLO);
|
||||||
|
|
||||||
int opts;
|
int opts;
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
@ -1128,19 +1107,19 @@ public final class OpenSslEngine extends SSLEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((opts & SSL.SSL_OP_NO_TLSv1) == 0) {
|
if ((opts & SSL.SSL_OP_NO_TLSv1) == 0) {
|
||||||
enabled.add(PROTOCOL_TLS_V1);
|
enabled.add(OpenSsl.PROTOCOL_TLS_V1);
|
||||||
}
|
}
|
||||||
if ((opts & SSL.SSL_OP_NO_TLSv1_1) == 0) {
|
if ((opts & SSL.SSL_OP_NO_TLSv1_1) == 0) {
|
||||||
enabled.add(PROTOCOL_TLS_V1_1);
|
enabled.add(OpenSsl.PROTOCOL_TLS_V1_1);
|
||||||
}
|
}
|
||||||
if ((opts & SSL.SSL_OP_NO_TLSv1_2) == 0) {
|
if ((opts & SSL.SSL_OP_NO_TLSv1_2) == 0) {
|
||||||
enabled.add(PROTOCOL_TLS_V1_2);
|
enabled.add(OpenSsl.PROTOCOL_TLS_V1_2);
|
||||||
}
|
}
|
||||||
if ((opts & SSL.SSL_OP_NO_SSLv2) == 0) {
|
if ((opts & SSL.SSL_OP_NO_SSLv2) == 0) {
|
||||||
enabled.add(PROTOCOL_SSL_V2);
|
enabled.add(OpenSsl.PROTOCOL_SSL_V2);
|
||||||
}
|
}
|
||||||
if ((opts & SSL.SSL_OP_NO_SSLv3) == 0) {
|
if ((opts & SSL.SSL_OP_NO_SSLv3) == 0) {
|
||||||
enabled.add(PROTOCOL_SSL_V3);
|
enabled.add(OpenSsl.PROTOCOL_SSL_V3);
|
||||||
}
|
}
|
||||||
return enabled.toArray(new String[enabled.size()]);
|
return enabled.toArray(new String[enabled.size()]);
|
||||||
}
|
}
|
||||||
@ -1157,18 +1136,18 @@ public final class OpenSslEngine extends SSLEngine {
|
|||||||
boolean tlsv1_1 = false;
|
boolean tlsv1_1 = false;
|
||||||
boolean tlsv1_2 = false;
|
boolean tlsv1_2 = false;
|
||||||
for (String p: protocols) {
|
for (String p: protocols) {
|
||||||
if (!SUPPORTED_PROTOCOLS_SET.contains(p)) {
|
if (!OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(p)) {
|
||||||
throw new IllegalArgumentException("Protocol " + p + " is not supported.");
|
throw new IllegalArgumentException("Protocol " + p + " is not supported.");
|
||||||
}
|
}
|
||||||
if (p.equals(PROTOCOL_SSL_V2)) {
|
if (p.equals(OpenSsl.PROTOCOL_SSL_V2)) {
|
||||||
sslv2 = true;
|
sslv2 = true;
|
||||||
} else if (p.equals(PROTOCOL_SSL_V3)) {
|
} else if (p.equals(OpenSsl.PROTOCOL_SSL_V3)) {
|
||||||
sslv3 = true;
|
sslv3 = true;
|
||||||
} else if (p.equals(PROTOCOL_TLS_V1)) {
|
} else if (p.equals(OpenSsl.PROTOCOL_TLS_V1)) {
|
||||||
tlsv1 = true;
|
tlsv1 = true;
|
||||||
} else if (p.equals(PROTOCOL_TLS_V1_1)) {
|
} else if (p.equals(OpenSsl.PROTOCOL_TLS_V1_1)) {
|
||||||
tlsv1_1 = true;
|
tlsv1_1 = true;
|
||||||
} else if (p.equals(PROTOCOL_TLS_V1_2)) {
|
} else if (p.equals(OpenSsl.PROTOCOL_TLS_V1_2)) {
|
||||||
tlsv1_2 = true;
|
tlsv1_2 = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user