From f34a0098341852db0e17ef3ac39f2ff2ee4a23ad Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sun, 30 Nov 2014 02:01:26 -0500 Subject: [PATCH] Don't set s->state and s->server before the side is known. If SSL_clear is called before SSL_set_{connect,accept}_state (as SSL_new does internally), s->state will get set prematurely. Likewise, s->server is set based on the method's ssl_accept hook, but client SSL's may be initialized from a generic SSL_METHOD too. Since we can't easily get rid of the generic SSL_METHODs, defer s->state and s->server initialization until the side is known. Change-Id: I0972e17083df22a3c09f6f087011b54c699a22e7 Reviewed-on: https://boringssl-review.googlesource.com/2439 Reviewed-by: Adam Langley --- include/openssl/ssl.h | 6 +++++- ssl/ssl_lib.c | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 66ae1283..2a388c7c 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1188,7 +1188,11 @@ struct ssl_st * test instead of an "init" member. */ - int server; /* are we the server side? - mostly used by SSL_clear*/ + /* server is true iff the this SSL* is the server half. Note: + * before the SSL* is initialized by either + * SSL_set_accept_state or SSL_set_connect_state, the side is + * not determined. In this state, server is always false. */ + int server; int new_session;/* Generate a new session or reuse an old one. * NB: For servers, the 'new' session may actually be a previously diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 80a8c2b6..783e8aef 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -210,7 +210,20 @@ int SSL_clear(SSL *s) } #endif - s->state=SSL_ST_BEFORE|((s->server)?SSL_ST_ACCEPT:SSL_ST_CONNECT); + /* SSL_clear may be called before or after the |s| is initialized in + * either accept or connect state. In the latter case, SSL_clear should + * preserve the half and reset |s->state| accordingly. */ + if (s->handshake_func != NULL) + { + if (s->server) + SSL_set_accept_state(s); + else + SSL_set_connect_state(s); + } + else + { + assert(s->state == 0); + } s->version=s->method->version; s->client_version=s->version; @@ -369,7 +382,6 @@ SSL *SSL_new(SSL_CTX *ctx) goto err; s->references=1; - s->server=(ctx->method->ssl_accept == ssl_undefined_function)?0:1; SSL_clear(s);