Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add sslv2 client hello test w/ jvm #5019

Merged
merged 11 commits into from
Jan 16, 2025
2 changes: 1 addition & 1 deletion codebuild/spec/buildspec_ubuntu_integrationv2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ batch:
- openssl-1.1.1_gcc9
- openssl-3.0
INTEGV2_TEST:
- "test_dynamic_record_sizes test_sslyze"
- "test_dynamic_record_sizes test_sslyze test_sslv2_client_hello"

env:
variables:
Expand Down
18 changes: 13 additions & 5 deletions tests/integrationv2/bin/SSLSocketClient.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.security.KeyStore;
import java.io.FileInputStream;
import java.io.OutputStream;
Expand All @@ -18,14 +19,18 @@ public class SSLSocketClient {
public static void main(String[] args) throws Exception {
int port = Integer.parseInt(args[0]);
String certificatePath = args[1];
String protocol = sslProtocols(args[2]);
String[] protocolList = new String[] {protocol};
String[] cipher = new String[] {args[3]};
String[] cipher = new String[] {args[2]};
// We assume that args[3] is the intended protocol to negotiated, like "TLS1.3"
// or "TLS1.2". args[4] is optional, and if included it's value must be "SSLv2Hello".
jmayclin marked this conversation as resolved.
Show resolved Hide resolved
String[] protocolList = Arrays.copyOfRange(args, 3, args.length);
for (int i = 0; i < protocolList.length; i++) {
protocolList[i] = sslProtocols(protocolList[i]);
}

String host = "localhost";
byte[] buffer = new byte[100];

SSLSocketFactory socketFactory = createSocketFactory(certificatePath, protocol);
SSLSocketFactory socketFactory = createSocketFactory(certificatePath, protocolList[0]);

jmayclin marked this conversation as resolved.
Show resolved Hide resolved
try (
SSLSocket socket = (SSLSocket)socketFactory.createSocket(host, port);
Expand Down Expand Up @@ -92,8 +97,11 @@ public static String sslProtocols(String s2nProtocol) {
return "TLSv1.1";
case "TLS1.0":
return "TLSv1.0";
// This "protocol" forces the ClientHello message to use SSLv2 format.
case "SSLv2Hello":
return "SSLv2Hello";
}

return null;
throw new RuntimeException("unrecognized protocol version:" + s2nProtocol);
}
}
3 changes: 2 additions & 1 deletion tests/integrationv2/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ class Protocols(object):
TLS11 = Protocol("TLS1.1", 32)
TLS10 = Protocol("TLS1.0", 31)
SSLv3 = Protocol("SSLv3", 30)
SSLv2 = Protocol("SSLv2", 20)


class Cipher(object):
Expand Down Expand Up @@ -567,7 +568,7 @@ def __init__(
# Boolean whether to use a resumption ticket
self.use_session_ticket = use_session_ticket

# Boolean whether to allow insecure certificates
# Boolean whether to disable x509 verification
self.insecure = insecure

# Which protocol to use with this provider
Expand Down
9 changes: 6 additions & 3 deletions tests/integrationv2/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,12 +600,15 @@ def setup_client(self):
cmd_line.extend([self.options.trust_store])
elif self.options.cert:
cmd_line.extend([self.options.cert])
if self.options.cipher.iana_standard_name is not None:
cmd_line.extend([self.options.cipher.iana_standard_name])

if self.options.protocol is not None:
cmd_line.extend([self.options.protocol.name])

if self.options.cipher.iana_standard_name is not None:
cmd_line.extend([self.options.cipher.iana_standard_name])
# SSLv2ClientHello is a "protocol" for Java TLS, so we append it next to
# the existing protocol.
if self.options.extra_flags is not None:
cmd_line.extend(self.options.extra_flags)

# Clients are always ready to connect
self.set_provider_ready()
Expand Down
74 changes: 74 additions & 0 deletions tests/integrationv2/test_sslv2_client_hello.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
import copy

from configuration import available_ports
from common import Certificates, Ciphers, Protocols, ProviderOptions, data_bytes
from fixtures import managed_process # lgtm [py/unused-import]
from providers import Provider, S2N, JavaSSL
from utils import (
to_bytes,
)


def test_s2n_server_sslv2_client_hello(managed_process):
# TLS 1.3: not supported by SSLv2 ClientHellos
# TLS 1.2: supported
# TLS 1.0 - TLS 1.1: not supported by Java
TEST_PROTOCOL = Protocols.TLS12

port = next(available_ports)

# s2nd can receive large amounts of data because all the data is
# echo'd to stdout unmodified. This lets us compare received to
# expected easily.
# We purposefully send a non block aligned number to make sure
# nothing blocks waiting for more data.
random_bytes = data_bytes(65519)

certificate = Certificates.RSA_2048_SHA256

client_options = ProviderOptions(
mode=Provider.ClientMode,
port=port,
# The cipher must use RSA key exchange. ECDHE is not supported with
# SSLv2 formatted client hellos.
cipher=Ciphers.AES256_SHA256,
cert=certificate.cert,
data_to_send=random_bytes,
insecure=True,
protocol=TEST_PROTOCOL,
extra_flags=["SSLv2Hello"],
)

server_options = copy.copy(client_options)
server_options.mode = Provider.ServerMode
server_options.data_to_send = None
server_options.key = certificate.key
server_options.cert = certificate.cert
server_options.extra_flags = None

# Passing the type of client and server as a parameter will
# allow us to use a fixture to enumerate all possibilities.
server = managed_process(S2N, server_options, timeout=5)
client = managed_process(JavaSSL, client_options, timeout=5)

# The client will be one of all supported providers. We
# just want to make sure there was no exception and that
# the client exited cleanly.
for client_results in client.get_results():
client_results.assert_success()

# The server is always S2N in this test, so we can examine
# the stdout reliably.
for server_results in server.get_results():
server_results.assert_success()
assert (
to_bytes(f"Client hello version: {Protocols.SSLv2.value}")
in server_results.stdout
)
assert (
to_bytes(f"Actual protocol version: {TEST_PROTOCOL.value}")
in server_results.stdout
)
assert random_bytes in server_results.stdout
Loading