Skip to content

Commit

Permalink
Allow to enable/disable protocols on the OpenSslEngine
Browse files Browse the repository at this point in the history
Motivation:

To be compatible with SSLEngine we need to support enable / disable procols on the OpenSslEngine

Modifications:

Implement OpenSslEngine.getSupportedProtocols() , getEnabledProtocols() and setEnabledProtocols(...)

Result:

Better compability with SSLEngine
  • Loading branch information
normanmaurer committed Dec 26, 2014
1 parent 7423db0 commit 8a1c7f2
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,12 @@ static OpenSslApplicationProtocolNegotiator toNegotiator(ApplicationProtocolConf
return OpenSslDefaultApplicationProtocolNegotiator.INSTANCE;
}

switch(config.protocol()) {
switch (config.protocol()) {
case NONE:
return OpenSslDefaultApplicationProtocolNegotiator.INSTANCE;
case NPN:
if (isServer) {
switch(config.selectedListenerFailureBehavior()) {
switch (config.selectedListenerFailureBehavior()) {
case CHOOSE_MY_LAST_PROTOCOL:
return new OpenSslNpnApplicationProtocolNegotiator(config.supportedProtocols());
default:
Expand Down
97 changes: 93 additions & 4 deletions handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,13 @@
import java.nio.ReadOnlyBufferException;
import java.security.Principal;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -82,6 +87,24 @@ public final class OpenSslEngine extends SSLEngine {
private static final int MAX_COMPRESSED_LENGTH = MAX_PLAINTEXT_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)
static final int MAX_ENCRYPTED_PACKET_LENGTH = MAX_CIPHERTEXT_LENGTH + 5 + 20 + 256;

Expand Down Expand Up @@ -644,17 +667,83 @@ public void setEnabledCipherSuites(String[] strings) {

@Override
public String[] getSupportedProtocols() {
return EmptyArrays.EMPTY_STRINGS;
return SUPPORTED_PROTOCOLS.clone();
}

@Override
public String[] getEnabledProtocols() {
return EmptyArrays.EMPTY_STRINGS;
List<String> enabled = new ArrayList<String>();
// Seems like there is no way to explict disable SSLv2Hello in openssl so it is always enabled
enabled.add(PROTOCOL_SSL_V2_HELLO);
int opts = SSL.getOptions(ssl);
if ((opts & SSL.SSL_OP_NO_TLSv1) == 0) {
enabled.add(PROTOCOL_TLS_V1);
}
if ((opts & SSL.SSL_OP_NO_TLSv1_1) == 0) {
enabled.add(PROTOCOL_TLS_V1_1);
}
if ((opts & SSL.SSL_OP_NO_TLSv1_2) == 0) {
enabled.add(PROTOCOL_TLS_V1_2);
}
if ((opts & SSL.SSL_OP_NO_SSLv2) == 0) {
enabled.add(PROTOCOL_SSL_V2);
}
if ((opts & SSL.SSL_OP_NO_SSLv3) == 0) {
enabled.add(PROTOCOL_SSL_V3);
}
int size = enabled.size();
if (size == 0) {
return EmptyArrays.EMPTY_STRINGS;
} else {
return enabled.toArray(new String[size]);
}
}

@Override
public void setEnabledProtocols(String[] strings) {
throw new UnsupportedOperationException();
public void setEnabledProtocols(String[] protocols) {
if (protocols == null) {
// This is correct from the API docs
throw new IllegalArgumentException();
}
boolean sslv2 = false;
boolean sslv3 = false;
boolean tlsv1 = false;
boolean tlsv1_1 = false;
boolean tlsv1_2 = false;
for (String p: protocols) {
if (!SUPPORTED_PROTOCOLS_SET.contains(p)) {
throw new IllegalArgumentException("Protocol " + p + " is not supported.");
}
if (p.equals(PROTOCOL_SSL_V2)) {
sslv2 = true;
} else if (p.equals(PROTOCOL_SSL_V3)) {
sslv3 = true;
} else if (p.equals(PROTOCOL_TLS_V1)) {
tlsv1 = true;
} else if (p.equals(PROTOCOL_TLS_V1_1)) {
tlsv1_1 = true;
} else if (p.equals(PROTOCOL_TLS_V1_2)) {
tlsv1_2 = true;
}
}
// Enable all and then disable what we not want
SSL.setOptions(ssl, SSL.SSL_OP_ALL);

if (!sslv2) {
SSL.setOptions(ssl, SSL.SSL_OP_NO_SSLv2);
}
if (!sslv3) {
SSL.setOptions(ssl, SSL.SSL_OP_NO_SSLv3);
}
if (!tlsv1) {
SSL.setOptions(ssl, SSL.SSL_OP_NO_TLSv1);
}
if (!tlsv1_1) {
SSL.setOptions(ssl, SSL.SSL_OP_NO_TLSv1_1);
}
if (!tlsv1_2) {
SSL.setOptions(ssl, SSL.SSL_OP_NO_TLSv1_2);
}
}

private Certificate[] initPeerCertChain() throws SSLPeerUnverifiedException {
Expand Down

0 comments on commit 8a1c7f2

Please sign in to comment.