Add a unit test for one-sided shutdown.
OpenSSL was actually super-buggy here (though known bugs on our end have been fixed), but pyOpenSSL was confused and incorrectly documented that callers call SSL_read after SSL_shutdown to do bidi shutdown, so we should probably support this. Add a test that it works. Change-Id: I2b6d012161330aeb4cf894bae3a0b6a55d53c70d Reviewed-on: https://boringssl-review.googlesource.com/8093 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
parent
bbd43b5e90
commit
686bb19ba1
105
ssl/ssl_test.cc
105
ssl/ssl_test.cc
@ -1079,23 +1079,9 @@ static ScopedEVP_PKEY GetTestKey() {
|
|||||||
PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
|
PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool TestSequenceNumber(bool dtls) {
|
static bool ConnectClientAndServer(ScopedSSL *out_client, ScopedSSL *out_server,
|
||||||
ScopedSSL_CTX client_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
|
SSL_CTX *client_ctx, SSL_CTX *server_ctx) {
|
||||||
ScopedSSL_CTX server_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
|
ScopedSSL client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
|
||||||
if (!client_ctx || !server_ctx) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopedX509 cert = GetTestCertificate();
|
|
||||||
ScopedEVP_PKEY key = GetTestKey();
|
|
||||||
if (!cert || !key ||
|
|
||||||
!SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
|
|
||||||
!SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a client and server connected to each other.
|
|
||||||
ScopedSSL client(SSL_new(client_ctx.get())), server(SSL_new(server_ctx.get()));
|
|
||||||
if (!client || !server) {
|
if (!client || !server) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1135,6 +1121,32 @@ static bool TestSequenceNumber(bool dtls) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*out_client = std::move(client);
|
||||||
|
*out_server = std::move(server);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TestSequenceNumber(bool dtls) {
|
||||||
|
ScopedSSL_CTX client_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
|
||||||
|
ScopedSSL_CTX server_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
|
||||||
|
if (!client_ctx || !server_ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedX509 cert = GetTestCertificate();
|
||||||
|
ScopedEVP_PKEY key = GetTestKey();
|
||||||
|
if (!cert || !key ||
|
||||||
|
!SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
|
||||||
|
!SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedSSL client, server;
|
||||||
|
if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
|
||||||
|
server_ctx.get())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t client_read_seq = SSL_get_read_sequence(client.get());
|
uint64_t client_read_seq = SSL_get_read_sequence(client.get());
|
||||||
uint64_t client_write_seq = SSL_get_write_sequence(client.get());
|
uint64_t client_write_seq = SSL_get_write_sequence(client.get());
|
||||||
uint64_t server_read_seq = SSL_get_read_sequence(server.get());
|
uint64_t server_read_seq = SSL_get_read_sequence(server.get());
|
||||||
@ -1183,6 +1195,62 @@ static bool TestSequenceNumber(bool dtls) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool TestOneSidedShutdown() {
|
||||||
|
ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method()));
|
||||||
|
ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method()));
|
||||||
|
if (!client_ctx || !server_ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedX509 cert = GetTestCertificate();
|
||||||
|
ScopedEVP_PKEY key = GetTestKey();
|
||||||
|
if (!cert || !key ||
|
||||||
|
!SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
|
||||||
|
!SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedSSL client, server;
|
||||||
|
if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
|
||||||
|
server_ctx.get())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shut down half the connection. SSL_shutdown will return 0 to signal only
|
||||||
|
// one side has shut down.
|
||||||
|
if (SSL_shutdown(client.get()) != 0) {
|
||||||
|
fprintf(stderr, "Could not shutdown.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reading from the server should consume the EOF.
|
||||||
|
uint8_t byte;
|
||||||
|
if (SSL_read(server.get(), &byte, 1) != 0 ||
|
||||||
|
SSL_get_error(server.get(), 0) != SSL_ERROR_ZERO_RETURN) {
|
||||||
|
fprintf(stderr, "Connection was not shut down cleanly.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// However, the server may continue to write data and then shut down the
|
||||||
|
// connection.
|
||||||
|
byte = 42;
|
||||||
|
if (SSL_write(server.get(), &byte, 1) != 1 ||
|
||||||
|
SSL_read(client.get(), &byte, 1) != 1 ||
|
||||||
|
byte != 42) {
|
||||||
|
fprintf(stderr, "Could not send byte.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The server may then shutdown the connection.
|
||||||
|
if (SSL_shutdown(server.get()) != 1 ||
|
||||||
|
SSL_shutdown(client.get()) != 1) {
|
||||||
|
fprintf(stderr, "Could not complete shutdown.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
CRYPTO_library_init();
|
CRYPTO_library_init();
|
||||||
|
|
||||||
@ -1206,7 +1274,8 @@ int main() {
|
|||||||
!TestClientCAList() ||
|
!TestClientCAList() ||
|
||||||
!TestInternalSessionCache() ||
|
!TestInternalSessionCache() ||
|
||||||
!TestSequenceNumber(false /* TLS */) ||
|
!TestSequenceNumber(false /* TLS */) ||
|
||||||
!TestSequenceNumber(true /* DTLS */)) {
|
!TestSequenceNumber(true /* DTLS */) ||
|
||||||
|
!TestOneSidedShutdown()) {
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user