aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2017-01-13 14:25:15 +0000
committerMatt Caswell <matt@openssl.org>2017-01-30 10:17:52 +0000
commitbe62b22b527e89061f88c0b9eaefb0410982f41e (patch)
tree62bdce920d7922a0d72f87cdbc487811a6fa8b78 /apps
parentf05bcf0f4581664f429154cdb689faef242cf843 (diff)
downloadopenssl-be62b22b527e89061f88c0b9eaefb0410982f41e.tar.gz
Update the s_client -sess_out feature to work for TLSv1.3
Previously "-sess_out" wrote out the session as soon as the handshake finished. In TLSv1.3 this won't work because the NewSessionTicket message arrives post-handshake. Instead we use the session callback mechanism to do this. Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2259)
Diffstat (limited to 'apps')
-rw-r--r--apps/s_client.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/apps/s_client.c b/apps/s_client.c
index d2f10a6885..362f005cc5 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -90,6 +90,7 @@ static char *keymatexportlabel = NULL;
static int keymatexportlen = 20;
static BIO *bio_c_out = NULL;
static int c_quiet = 0;
+static char *sess_out = NULL;
static void print_stuff(BIO *berr, SSL *con, int full);
#ifndef OPENSSL_NO_OCSP
@@ -779,6 +780,24 @@ static void freeandcopy(char **dest, const char *source)
*dest = OPENSSL_strdup(source);
}
+static int new_session_cb(SSL *S, SSL_SESSION *sess)
+{
+ BIO *stmp = BIO_new_file(sess_out, "w");
+
+ if (stmp != NULL) {
+ PEM_write_bio_SSL_SESSION(stmp, sess);
+ BIO_free(stmp);
+ } else {
+ BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
+ }
+
+ /*
+ * We always return a "fail" response so that the session gets freed again
+ * because we haven't used the reference.
+ */
+ return 0;
+}
+
int s_client_main(int argc, char **argv)
{
BIO *sbio;
@@ -804,7 +823,7 @@ int s_client_main(int argc, char **argv)
char *port = OPENSSL_strdup(PORT);
char *inrand = NULL;
char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
- char *sess_in = NULL, *sess_out = NULL, *crl_file = NULL, *p;
+ char *sess_in = NULL, *crl_file = NULL, *p;
char *xmpphost = NULL;
const char *ehlo = "mail.example.com";
struct timeval timeout, *timeoutp;
@@ -1674,6 +1693,17 @@ int s_client_main(int argc, char **argv)
}
}
+ /*
+ * In TLSv1.3 NewSessionTicket messages arrive after the handshake and can
+ * come at any time. Therefore we use a callback to write out the session
+ * when we know about it. This approach works for < TLSv1.3 as well.
+ */
+ if (sess_out) {
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT
+ | SSL_SESS_CACHE_NO_INTERNAL_STORE);
+ SSL_CTX_sess_set_new_cb(ctx, new_session_cb);
+ }
+
con = SSL_new(ctx);
if (sess_in) {
SSL_SESSION *sess;
@@ -2168,15 +2198,6 @@ int s_client_main(int argc, char **argv)
tlsextcbp.ack ? "" : "not ");
}
- if (sess_out) {
- BIO *stmp = BIO_new_file(sess_out, "w");
- if (stmp) {
- PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con));
- BIO_free(stmp);
- } else
- BIO_printf(bio_err, "Error writing session file %s\n",
- sess_out);
- }
if (c_brief) {
BIO_puts(bio_err, "CONNECTION ESTABLISHED\n");
print_ssl_summary(con);