Adding new options for bssl tool.
* -loop on the server allows it to keep accepting connections.
* -resume on the client waits to receive a session from the server
and starts a new connection using the previous session.
Change-Id: I27a413c7c1d64edbca94aecc6f112d8d15afbce2
Reviewed-on: https://boringssl-review.googlesource.com/12630
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/tool/client.cc b/tool/client.cc
index b9f1c13..39cb7f0 100644
--- a/tool/client.cc
+++ b/tool/client.cc
@@ -16,6 +16,12 @@
#include <stdio.h>
+#if !defined(OPENSSL_WINDOWS)
+#include <sys/select.h>
+#else
+#include <winsock2.h>
+#endif
+
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
@@ -93,6 +99,10 @@
"Enable GREASE",
},
{
+ "-resume", kBooleanArgument,
+ "Establish a second connection resuming the original connection.",
+ },
+ {
"", kOptionalArgument, "",
},
};
@@ -122,6 +132,7 @@
}
static bssl::UniquePtr<BIO> session_out;
+static bssl::UniquePtr<SSL_SESSION> resume_session;
static int NewSessionCallback(SSL *ssl, SSL_SESSION *session) {
if (session_out) {
@@ -132,8 +143,105 @@
return 0;
}
}
+ resume_session = bssl::UniquePtr<SSL_SESSION>(session);
+ return 1;
+}
- return 0;
+static bool WaitForSession(SSL *ssl, int sock) {
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+
+ if (!SocketSetNonBlocking(sock, true)) {
+ return false;
+ }
+
+ while (!resume_session) {
+ FD_SET(sock, &read_fds);
+ int ret = select(sock + 1, &read_fds, NULL, NULL, NULL);
+ if (ret <= 0) {
+ perror("select");
+ return false;
+ }
+
+ uint8_t buffer[512];
+ int ssl_ret = SSL_read(ssl, buffer, sizeof(buffer));
+
+ if (ssl_ret <= 0) {
+ int ssl_err = SSL_get_error(ssl, ssl_ret);
+ if (ssl_err == SSL_ERROR_WANT_READ) {
+ continue;
+ }
+ fprintf(stderr, "Error while reading: %d\n", ssl_err);
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool DoConnection(SSL_CTX *ctx,
+ std::map<std::string, std::string> args_map,
+ bool (*cb)(SSL *ssl, int sock)) {
+ int sock = -1;
+ if (!Connect(&sock, args_map["-connect"])) {
+ return false;
+ }
+
+ if (args_map.count("-starttls") != 0) {
+ const std::string& starttls = args_map["-starttls"];
+ if (starttls == "smtp") {
+ if (!DoSMTPStartTLS(sock)) {
+ return false;
+ }
+ } else {
+ fprintf(stderr, "Unknown value for -starttls: %s\n", starttls.c_str());
+ return false;
+ }
+ }
+
+ bssl::UniquePtr<BIO> bio(BIO_new_socket(sock, BIO_CLOSE));
+ bssl::UniquePtr<SSL> ssl(SSL_new(ctx));
+
+ if (args_map.count("-server-name") != 0) {
+ SSL_set_tlsext_host_name(ssl.get(), args_map["-server-name"].c_str());
+ }
+
+ if (args_map.count("-session-in") != 0) {
+ bssl::UniquePtr<BIO> in(BIO_new_file(args_map["-session-in"].c_str(),
+ "rb"));
+ if (!in) {
+ fprintf(stderr, "Error reading session\n");
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ }
+ bssl::UniquePtr<SSL_SESSION> session(PEM_read_bio_SSL_SESSION(in.get(),
+ nullptr, nullptr, nullptr));
+ if (!session) {
+ fprintf(stderr, "Error reading session\n");
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ }
+ SSL_set_session(ssl.get(), session.get());
+ } else if (resume_session) {
+ SSL_set_session(ssl.get(), resume_session.get());
+ }
+
+ SSL_set_bio(ssl.get(), bio.get(), bio.get());
+ bio.release();
+
+ int ret = SSL_connect(ssl.get());
+ if (ret != 1) {
+ int ssl_err = SSL_get_error(ssl.get(), ret);
+ fprintf(stderr, "Error while connecting: %d\n", ssl_err);
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ }
+
+ fprintf(stderr, "Connected.\n");
+ PrintConnectionInfo(ssl.get());
+
+ return cb(ssl.get(), sock);
}
bool Client(const std::vector<std::string> &args) {
@@ -261,6 +369,9 @@
}
}
+ SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_CLIENT);
+ SSL_CTX_sess_set_new_cb(ctx.get(), NewSessionCallback);
+
if (args_map.count("-session-out") != 0) {
session_out.reset(BIO_new_file(args_map["-session-out"].c_str(), "wb"));
if (!session_out) {
@@ -269,71 +380,16 @@
ERR_print_errors_cb(PrintErrorCallback, stderr);
return false;
}
- SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_CLIENT);
- SSL_CTX_sess_set_new_cb(ctx.get(), NewSessionCallback);
}
if (args_map.count("-grease") != 0) {
SSL_CTX_set_grease_enabled(ctx.get(), 1);
}
- int sock = -1;
- if (!Connect(&sock, args_map["-connect"])) {
+ if (args_map.count("-resume") != 0 &&
+ !DoConnection(ctx.get(), args_map, &WaitForSession)) {
return false;
}
- if (args_map.count("-starttls") != 0) {
- const std::string& starttls = args_map["-starttls"];
- if (starttls == "smtp") {
- if (!DoSMTPStartTLS(sock)) {
- return false;
- }
- } else {
- fprintf(stderr, "Unknown value for -starttls: %s\n", starttls.c_str());
- return false;
- }
- }
-
- bssl::UniquePtr<BIO> bio(BIO_new_socket(sock, BIO_CLOSE));
- bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
-
- if (args_map.count("-server-name") != 0) {
- SSL_set_tlsext_host_name(ssl.get(), args_map["-server-name"].c_str());
- }
-
- if (args_map.count("-session-in") != 0) {
- bssl::UniquePtr<BIO> in(BIO_new_file(args_map["-session-in"].c_str(),
- "rb"));
- if (!in) {
- fprintf(stderr, "Error reading session\n");
- ERR_print_errors_cb(PrintErrorCallback, stderr);
- return false;
- }
- bssl::UniquePtr<SSL_SESSION> session(PEM_read_bio_SSL_SESSION(in.get(),
- nullptr, nullptr, nullptr));
- if (!session) {
- fprintf(stderr, "Error reading session\n");
- ERR_print_errors_cb(PrintErrorCallback, stderr);
- return false;
- }
- SSL_set_session(ssl.get(), session.get());
- }
-
- SSL_set_bio(ssl.get(), bio.get(), bio.get());
- bio.release();
-
- int ret = SSL_connect(ssl.get());
- if (ret != 1) {
- int ssl_err = SSL_get_error(ssl.get(), ret);
- fprintf(stderr, "Error while connecting: %d\n", ssl_err);
- ERR_print_errors_cb(PrintErrorCallback, stderr);
- return false;
- }
-
- fprintf(stderr, "Connected.\n");
- PrintConnectionInfo(ssl.get());
-
- bool ok = TransferData(ssl.get(), sock);
-
- return ok;
+ return DoConnection(ctx.get(), args_map, &TransferData);
}
diff --git a/tool/server.cc b/tool/server.cc
index a049422..94abbbd 100644
--- a/tool/server.cc
+++ b/tool/server.cc
@@ -24,33 +24,37 @@
static const struct argument kArguments[] = {
{
- "-accept", kRequiredArgument,
- "The port of the server to bind on; eg 45102",
+ "-accept", kRequiredArgument,
+ "The port of the server to bind on; eg 45102",
},
{
- "-cipher", kOptionalArgument,
- "An OpenSSL-style cipher suite string that configures the offered ciphers",
+ "-cipher", kOptionalArgument,
+ "An OpenSSL-style cipher suite string that configures the offered "
+ "ciphers",
},
{
- "-max-version", kOptionalArgument,
- "The maximum acceptable protocol version",
+ "-max-version", kOptionalArgument,
+ "The maximum acceptable protocol version",
},
{
- "-min-version", kOptionalArgument,
- "The minimum acceptable protocol version",
+ "-min-version", kOptionalArgument,
+ "The minimum acceptable protocol version",
},
{
- "-key", kOptionalArgument,
- "PEM-encoded file containing the private key, leaf certificate and "
- "optional certificate chain. A self-signed certificate is generated "
- "at runtime if this argument is not provided.",
+ "-key", kOptionalArgument,
+ "PEM-encoded file containing the private key, leaf certificate and "
+ "optional certificate chain. A self-signed certificate is generated "
+ "at runtime if this argument is not provided.",
},
{
- "-ocsp-response", kOptionalArgument,
- "OCSP response file to send",
+ "-ocsp-response", kOptionalArgument, "OCSP response file to send",
},
{
- "", kOptionalArgument, "",
+ "-loop", kBooleanArgument,
+ "The server will continue accepting new sequential connections.",
+ },
+ {
+ "", kOptionalArgument, "",
},
};
@@ -219,25 +223,30 @@
return false;
}
- int sock = -1;
- if (!Accept(&sock, args_map["-accept"])) {
- return false;
- }
+ bool result = true;
+ do {
+ int sock = -1;
+ if (!Accept(&sock, args_map["-accept"])) {
+ return false;
+ }
- BIO *bio = BIO_new_socket(sock, BIO_CLOSE);
- bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
- SSL_set_bio(ssl.get(), bio, bio);
+ BIO *bio = BIO_new_socket(sock, BIO_CLOSE);
+ bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+ SSL_set_bio(ssl.get(), bio, bio);
- int ret = SSL_accept(ssl.get());
- if (ret != 1) {
- int ssl_err = SSL_get_error(ssl.get(), ret);
- fprintf(stderr, "Error while connecting: %d\n", ssl_err);
- ERR_print_errors_cb(PrintErrorCallback, stderr);
- return false;
- }
+ int ret = SSL_accept(ssl.get());
+ if (ret != 1) {
+ int ssl_err = SSL_get_error(ssl.get(), ret);
+ fprintf(stderr, "Error while connecting: %d\n", ssl_err);
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ }
- fprintf(stderr, "Connected.\n");
- PrintConnectionInfo(ssl.get());
+ fprintf(stderr, "Connected.\n");
+ PrintConnectionInfo(ssl.get());
- return TransferData(ssl.get(), sock);
+ result = TransferData(ssl.get(), sock);
+ } while (result && args_map.count("-loop") != 0);
+
+ return result;
}