aboutsummaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'ssl')
-rw-r--r--ssl/ssl_lib.c10
-rw-r--r--ssl/ssl_sess.c9
-rw-r--r--ssl/statem/extensions.c25
-rw-r--r--ssl/statem/extensions_srvr.c19
4 files changed, 43 insertions, 20 deletions
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 38391fd2c0..10a76940dd 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2612,7 +2612,15 @@ const char *SSL_get_servername(const SSL *s, const int type)
if (type != TLSEXT_NAMETYPE_host_name)
return NULL;
- return s->session && !s->ext.hostname ?
+ /*
+ * TODO(OpenSSL1.2) clean up this compat mess. This API is
+ * currently a mix of "what did I configure" and "what did the
+ * peer send" and "what was actually negotiated"; we should have
+ * a clear distinction amongst those three.
+ */
+ if (SSL_in_init(s))
+ return s->ext.hostname;
+ return (s->session != NULL && s->ext.hostname == NULL) ?
s->session->ext.hostname : s->ext.hostname;
}
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 628b9f060b..d4a4808f19 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -421,15 +421,6 @@ int ssl_get_new_session(SSL *s, int session)
return 0;
}
- if (s->ext.hostname) {
- ss->ext.hostname = OPENSSL_strdup(s->ext.hostname);
- if (ss->ext.hostname == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION,
- ERR_R_INTERNAL_ERROR);
- SSL_SESSION_free(ss);
- return 0;
- }
- }
} else {
ss->session_id_length = 0;
}
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index 5309b12703..85945acc0d 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -929,9 +929,28 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
ret = s->session_ctx->ext.servername_cb(s, &altmp,
s->session_ctx->ext.servername_arg);
- if (!sent) {
- OPENSSL_free(s->session->ext.hostname);
- s->session->ext.hostname = NULL;
+ /*
+ * For servers, propagate the SNI hostname from the temporary
+ * storage in the SSL to the persistent SSL_SESSION, now that we
+ * know we accepted it.
+ * Clients make this copy when parsing the server's response to
+ * the extension, which is when they find out that the negotiation
+ * was successful.
+ */
+ if (s->server) {
+ if (!sent) {
+ /* Nothing from the client this handshake; cleanup stale value */
+ OPENSSL_free(s->ext.hostname);
+ s->ext.hostname = NULL;
+ } else if (ret == SSL_TLSEXT_ERR_OK && (!s->hit || SSL_IS_TLS13(s))) {
+ /* Only store the hostname in the session if we accepted it. */
+ OPENSSL_free(s->session->ext.hostname);
+ s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
+ if (s->session->ext.hostname == NULL && s->ext.hostname != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ }
+ }
}
/*
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index f5ab5bb840..00c0ec9c09 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -127,7 +127,7 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
return 0;
}
- if (!s->hit) {
+ if (!s->hit || SSL_IS_TLS13(s)) {
if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
@@ -142,21 +142,26 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
return 0;
}
- OPENSSL_free(s->session->ext.hostname);
- s->session->ext.hostname = NULL;
- if (!PACKET_strndup(&hostname, &s->session->ext.hostname)) {
+ /*
+ * Store the requested SNI in the SSL as temporary storage.
+ * If we accept it, it will get stored in the SSL_SESSION as well.
+ */
+ OPENSSL_free(s->ext.hostname);
+ s->ext.hostname = NULL;
+ if (!PACKET_strndup(&hostname, &s->ext.hostname)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->servername_done = 1;
- } else {
+ }
+ if (s->hit) {
/*
* TODO(openssl-team): if the SNI doesn't match, we MUST
* fall back to a full handshake.
*/
- s->servername_done = s->session->ext.hostname
+ s->servername_done = (s->session->ext.hostname != NULL)
&& PACKET_equal(&hostname, s->session->ext.hostname,
strlen(s->session->ext.hostname));
@@ -1325,7 +1330,7 @@ EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
size_t chainidx)
{
if (s->hit || s->servername_done != 1
- || s->session->ext.hostname == NULL)
+ || s->ext.hostname == NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)