From 439db0c97bd50cae008e876c6c8ed5e5011bf6eb Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 1 Mar 2017 12:11:51 +0000 Subject: [PATCH] Add compression tests Check whether we negotiate compression in various scenarios. Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/2814) --- test/handshake_helper.c | 3 + test/handshake_helper.h | 1 + test/recipes/80-test_ssl_new.t | 4 +- test/ssl-tests/22-compression.conf | 112 +++++++++++++++++++++++ test/ssl-tests/22-compression.conf.in | 127 ++++++++++++++++++++++++++ test/ssl_test.c | 11 +++ test/ssl_test_ctx.c | 24 +++++ test/ssl_test_ctx.h | 7 ++ test/ssl_test_ctx_test.c | 8 ++ test/ssl_test_ctx_test.conf | 3 + 10 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 test/ssl-tests/22-compression.conf create mode 100644 test/ssl-tests/22-compression.conf.in diff --git a/test/handshake_helper.c b/test/handshake_helper.c index 88f6aec894..99b6ad1941 100644 --- a/test/handshake_helper.c +++ b/test/handshake_helper.c @@ -1207,6 +1207,9 @@ static HANDSHAKE_RESULT *do_handshake_internal( ret->session_ticket = SSL_TEST_SESSION_TICKET_NO; else ret->session_ticket = SSL_TEST_SESSION_TICKET_YES; + ret->compression = (SSL_get_current_compression(client.ssl) == NULL) + ? SSL_TEST_COMPRESSION_NO + : SSL_TEST_COMPRESSION_YES; ret->session_ticket_do_not_call = server_ex_data.session_ticket_do_not_call; #ifndef OPENSSL_NO_NEXTPROTONEG diff --git a/test/handshake_helper.h b/test/handshake_helper.h index bdbeabb6fe..a9dd5c94a1 100644 --- a/test/handshake_helper.h +++ b/test/handshake_helper.h @@ -34,6 +34,7 @@ typedef struct handshake_result { ssl_servername_t servername; /* Session ticket status */ ssl_session_ticket_t session_ticket; + ssl_compression_t compression; /* Was this called on the second context? */ int session_ticket_do_not_call; char *client_npn_negotiated; diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index f94a7d84f8..5f4433403d 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -29,7 +29,7 @@ map { s/\^// } @conf_files if $^O eq "VMS"; # We hard-code the number of tests to double-check that the globbing above # finds all files as expected. -plan tests => 21; # = scalar @conf_srcs +plan tests => 22; # = scalar @conf_srcs # Some test results depend on the configuration of enabled protocols. We only # verify generated sources in the default configuration. @@ -63,6 +63,7 @@ my %conf_dependent_tests = ( "18-dtls-renegotiate.conf" => disabled("dtls1_2"), "19-mac-then-encrypt.conf" => !$is_default_tls, "20-cert-select.conf" => !$is_default_tls || $no_dh || $no_dsa, + "22-compression.conf" => !$is_default_tls, ); # Add your test here if it should be skipped for some compile-time @@ -87,6 +88,7 @@ my %skip = ( "19-mac-then-encrypt.conf" => $no_pre_tls1_3, "20-cert-select.conf" => disabled("tls1_2") || $no_ec, "21-key-update.conf" => disabled("tls1_3"), + "22-compression.conf" => disabled("zlib") || $no_tls, ); foreach my $conf (@conf_files) { diff --git a/test/ssl-tests/22-compression.conf b/test/ssl-tests/22-compression.conf new file mode 100644 index 0000000000..999b008ede --- /dev/null +++ b/test/ssl-tests/22-compression.conf @@ -0,0 +1,112 @@ +# Generated with generate_ssl_tests.pl + +num_tests = 4 + +test-0 = 0-tlsv1_2-both-compress +test-1 = 1-tlsv1_2-client-compress +test-2 = 2-tlsv1_2-server-compress +test-3 = 3-tlsv1_2-neither-compress +# =========================================================== + +[0-tlsv1_2-both-compress] +ssl_conf = 0-tlsv1_2-both-compress-ssl + +[0-tlsv1_2-both-compress-ssl] +server = 0-tlsv1_2-both-compress-server +client = 0-tlsv1_2-both-compress-client + +[0-tlsv1_2-both-compress-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +Options = Compression +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[0-tlsv1_2-both-compress-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.2 +Options = Compression +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-0] +CompressionExpected = Yes +ExpectedResult = Success + + +# =========================================================== + +[1-tlsv1_2-client-compress] +ssl_conf = 1-tlsv1_2-client-compress-ssl + +[1-tlsv1_2-client-compress-ssl] +server = 1-tlsv1_2-client-compress-server +client = 1-tlsv1_2-client-compress-client + +[1-tlsv1_2-client-compress-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[1-tlsv1_2-client-compress-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.2 +Options = Compression +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-1] +CompressionExpected = No +ExpectedResult = Success + + +# =========================================================== + +[2-tlsv1_2-server-compress] +ssl_conf = 2-tlsv1_2-server-compress-ssl + +[2-tlsv1_2-server-compress-ssl] +server = 2-tlsv1_2-server-compress-server +client = 2-tlsv1_2-server-compress-client + +[2-tlsv1_2-server-compress-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +Options = Compression +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[2-tlsv1_2-server-compress-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.2 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-2] +CompressionExpected = No +ExpectedResult = Success + + +# =========================================================== + +[3-tlsv1_2-neither-compress] +ssl_conf = 3-tlsv1_2-neither-compress-ssl + +[3-tlsv1_2-neither-compress-ssl] +server = 3-tlsv1_2-neither-compress-server +client = 3-tlsv1_2-neither-compress-client + +[3-tlsv1_2-neither-compress-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[3-tlsv1_2-neither-compress-client] +CipherString = DEFAULT +MaxProtocol = TLSv1.2 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-3] +CompressionExpected = No +ExpectedResult = Success + + diff --git a/test/ssl-tests/22-compression.conf.in b/test/ssl-tests/22-compression.conf.in new file mode 100644 index 0000000000..8d4d823345 --- /dev/null +++ b/test/ssl-tests/22-compression.conf.in @@ -0,0 +1,127 @@ +# -*- mode: perl; -*- +# Copyright 2016-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +## Test Compression + +use strict; +use warnings; + +package ssltests; +use OpenSSL::Test::Utils; + +our @tests = (); + +our @tests_tls1_3 = ( + { + name => "tlsv1_3-both-compress", + server => { + "Options" => "Compression" + }, + client => { + "Options" => "Compression" + }, + test => { + "CompressionExpected" => "No", + "ExpectedResult" => "Success" + } + }, + { + name => "tlsv1_3-client-compress", + server => { + }, + client => { + "Options" => "Compression" + }, + test => { + "CompressionExpected" => "No", + "ExpectedResult" => "Success" + } + }, + { + name => "tlsv1_3-server-compress", + server => { + "Options" => "Compression" + }, + client => { + }, + test => { + "CompressionExpected" => "No", + "ExpectedResult" => "Success" + } + }, + { + name => "tlsv1_3-neither-compress", + server => { + }, + client => { + }, + test => { + "CompressionExpected" => "No", + "ExpectedResult" => "Success" + } + }, +); +our @tests_tls1_2 = ( + { + name => "tlsv1_2-both-compress", + server => { + "Options" => "Compression" + }, + client => { + "Options" => "Compression", + "MaxProtocol" => "TLSv1.2" + }, + test => { + "CompressionExpected" => "Yes", + "ExpectedResult" => "Success" + } + }, + { + name => "tlsv1_2-client-compress", + server => { + }, + client => { + "Options" => "Compression", + "MaxProtocol" => "TLSv1.2" + }, + test => { + "CompressionExpected" => "No", + "ExpectedResult" => "Success" + } + }, + { + name => "tlsv1_2-server-compress", + server => { + "Options" => "Compression" + }, + client => { + "MaxProtocol" => "TLSv1.2" + }, + test => { + "CompressionExpected" => "No", + "ExpectedResult" => "Success" + } + }, + { + name => "tlsv1_2-neither-compress", + server => { + }, + client => { + "MaxProtocol" => "TLSv1.2" + }, + test => { + "CompressionExpected" => "No", + "ExpectedResult" => "Success" + } + }, +); + +push @tests, @tests_tls1_3 unless disabled("tls1_3"); +push @tests, @tests_tls1_2 unless alldisabled(("tls1_2", "tls1_1", "tls1", + "ssl3")); diff --git a/test/ssl_test.c b/test/ssl_test.c index 752de6396b..f5dfa97090 100644 --- a/test/ssl_test.c +++ b/test/ssl_test.c @@ -146,6 +146,16 @@ static int check_session_ticket(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx return 1; } +static int check_compression(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) +{ + if (result->compression != test_ctx->compression_expected) { + fprintf(stderr, "Client CompressionExpected mismatch, expected %s, got %s\n.", + ssl_compression_name(test_ctx->compression_expected), + ssl_compression_name(result->compression)); + return 0; + } + return 1; +} #ifndef OPENSSL_NO_NEXTPROTONEG static int check_npn(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) { @@ -259,6 +269,7 @@ static int check_test(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) ret &= check_protocol(result, test_ctx); ret &= check_servername(result, test_ctx); ret &= check_session_ticket(result, test_ctx); + ret &= check_compression(result, test_ctx); ret &= (result->session_ticket_do_not_call == 0); #ifndef OPENSSL_NO_NEXTPROTONEG ret &= check_npn(result, test_ctx); diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c index f9e74d11fd..e746dbd942 100644 --- a/test/ssl_test_ctx.c +++ b/test/ssl_test_ctx.c @@ -286,6 +286,29 @@ const char *ssl_session_ticket_name(ssl_session_ticket_t server) server); } +/* CompressionExpected */ + +static const test_enum ssl_compression[] = { + {"Yes", SSL_TEST_COMPRESSION_YES}, + {"No", SSL_TEST_COMPRESSION_NO}, +}; + +__owur static int parse_compression(SSL_TEST_CTX *test_ctx, const char *value) +{ + int ret_value; + if (!parse_enum(ssl_compression, OSSL_NELEM(ssl_compression), + &ret_value, value)) { + return 0; + } + test_ctx->compression_expected = ret_value; + return 1; +} + +const char *ssl_compression_name(ssl_compression_t comp) +{ + return enum_name(ssl_compression, OSSL_NELEM(ssl_compression), comp); +} + /* Method */ static const test_enum ssl_test_methods[] = { @@ -541,6 +564,7 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = { { "ExpectedProtocol", &parse_protocol }, { "ExpectedServerName", &parse_expected_servername }, { "SessionTicketExpected", &parse_session_ticket }, + { "CompressionExpected", &parse_compression }, { "Method", &parse_test_method }, { "ExpectedNPNProtocol", &parse_test_expected_npn_protocol }, { "ExpectedALPNProtocol", &parse_test_expected_alpn_protocol }, diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h index 499e314e3c..418a4f2ac3 100644 --- a/test/ssl_test_ctx.h +++ b/test/ssl_test_ctx.h @@ -51,6 +51,11 @@ typedef enum { SSL_TEST_SESSION_TICKET_BROKEN /* Special test */ } ssl_session_ticket_t; +typedef enum { + SSL_TEST_COMPRESSION_NO = 0, /* Default */ + SSL_TEST_COMPRESSION_YES +} ssl_compression_t; + typedef enum { SSL_TEST_METHOD_TLS = 0, /* Default */ SSL_TEST_METHOD_DTLS @@ -163,6 +168,7 @@ typedef struct { */ ssl_servername_t expected_servername; ssl_session_ticket_t session_ticket_expected; + ssl_compression_t compression_expected; /* The expected NPN/ALPN protocol to negotiate. */ char *expected_npn_protocol; char *expected_alpn_protocol; @@ -192,6 +198,7 @@ const char *ssl_servername_name(ssl_servername_t server); const char *ssl_servername_callback_name(ssl_servername_callback_t servername_callback); const char *ssl_session_ticket_name(ssl_session_ticket_t server); +const char *ssl_compression_name(ssl_compression_t server); const char *ssl_test_method_name(ssl_test_method_t method); const char *ssl_handshake_mode_name(ssl_handshake_mode_t mode); const char *ssl_ct_validation_name(ssl_ct_validation_t mode); diff --git a/test/ssl_test_ctx_test.c b/test/ssl_test_ctx_test.c index 36d17a7ba6..5c1e427e21 100644 --- a/test/ssl_test_ctx_test.c +++ b/test/ssl_test_ctx_test.c @@ -173,6 +173,12 @@ static int SSL_TEST_CTX_equal(SSL_TEST_CTX *ctx, SSL_TEST_CTX *ctx2) ssl_session_ticket_name(ctx2->session_ticket_expected)); return 0; } + if (ctx->compression_expected != ctx2->compression_expected) { + fprintf(stderr, "ComrpessionExpected mismatch: %s vs %s.\n", + ssl_compression_name(ctx->compression_expected), + ssl_compression_name(ctx2->compression_expected)); + return 0; + } if (!strings_equal("ExpectedNPNProtocol", ctx->expected_npn_protocol, ctx2->expected_npn_protocol)) return 0; @@ -250,6 +256,7 @@ static int test_good_configuration() fixture.expected_ctx->expected_protocol = TLS1_1_VERSION; fixture.expected_ctx->expected_servername = SSL_TEST_SERVERNAME_SERVER2; fixture.expected_ctx->session_ticket_expected = SSL_TEST_SESSION_TICKET_YES; + fixture.expected_ctx->compression_expected = SSL_TEST_COMPRESSION_NO; fixture.expected_ctx->resumption_expected = 1; fixture.expected_ctx->extra.client.verify_callback = @@ -284,6 +291,7 @@ static const char *bad_configurations[] = { "ssltest_unknown_servername", "ssltest_unknown_servername_callback", "ssltest_unknown_session_ticket_expected", + "ssltest_unknown_compression_expected", "ssltest_unknown_method", "ssltest_unknown_handshake_mode", "ssltest_unknown_resumption_expected", diff --git a/test/ssl_test_ctx_test.conf b/test/ssl_test_ctx_test.conf index a062d75a10..86d40e5486 100644 --- a/test/ssl_test_ctx_test.conf +++ b/test/ssl_test_ctx_test.conf @@ -72,6 +72,9 @@ ServerNameCallback = Foo [ssltest_unknown_session_ticket_expected] SessionTicketExpected = Foo +[ssltest_unknown_compression_expected] +CompressionExpected = Foo + [ssltest_unknown_method] Method = TLS2 -- 2.34.1