From 90084a133dc9fef84bd8bb30bafa947941701515 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Thu, 23 Nov 2017 18:21:29 +0100 Subject: [PATCH] MINOR: ssl: Handle reading early data after writing better. It can happen that we want to read early data, write some, and then continue reading them. To do so, we can't reuse tmp_early_data to store the amount of data sent, so introduce a new member. If we read early data, then ssl_sock_to_buf() is now the only responsible for getting back to the handshake, to make sure we don't miss any early data. --- include/proto/connection.h | 1 + include/types/connection.h | 1 + src/ssl_sock.c | 23 ++++++----------------- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/include/proto/connection.h b/include/proto/connection.h index 05a63fe6ad..c68ae20ba7 100644 --- a/include/proto/connection.h +++ b/include/proto/connection.h @@ -607,6 +607,7 @@ static inline void conn_init(struct connection *conn) conn->obj_type = OBJ_TYPE_CONN; conn->flags = CO_FL_NONE; conn->tmp_early_data = -1; + conn->sent_early_data = 0; conn->mux = NULL; conn->mux_ctx = NULL; conn->owner = NULL; diff --git a/include/types/connection.h b/include/types/connection.h index 88573b8a75..a9d04474db 100644 --- a/include/types/connection.h +++ b/include/types/connection.h @@ -373,6 +373,7 @@ struct connection { void *owner; /* pointer to the owner session for incoming connections, or NULL */ int xprt_st; /* transport layer state, initialized to zero */ int tmp_early_data; /* 1st byte of early data, if any */ + int sent_early_data; /* Amount of early data we sent so far */ union conn_handle handle; /* connection handle at the socket layer */ enum obj_type *target; /* the target to connect to (server, proxy, applet, ...) */ struct list list; /* attach point to various connection lists (idle, ...) */ diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 0fca243d2a..e98cc61f0e 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -1377,7 +1377,7 @@ void ssl_sock_infocbk(const SSL *ssl, int where, int ret) if (where & SSL_CB_HANDSHAKE_START) { /* Disable renegotiation (CVE-2009-3555) */ - if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS)) == CO_FL_CONNECTED) { + if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_CONNECTED) { conn->flags |= CO_FL_ERROR; conn->err_code = CO_ER_SSL_RENEG; } @@ -5318,15 +5318,6 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun /* let's realign the buffer to optimize I/O */ if (buffer_empty(buf)) { buf->p = buf->data; -#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) - /* - * If we're done reading the early data, and we're using - * a new buffer, then we know for sure we're not tainted - * with early data anymore - */ - if ((conn->flags & (CO_FL_EARLY_SSL_HS |CO_FL_EARLY_DATA)) == CO_FL_EARLY_DATA) - conn->flags &= ~CO_FL_EARLY_DATA; -#endif } /* read the largest possible block. For this, we perform only one call @@ -5499,9 +5490,6 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl if (!SSL_is_init_finished(conn->xprt_ctx)) { unsigned int max_early; - if (conn->tmp_early_data == -1) - conn->tmp_early_data = 0; - if (objt_listener(conn->target)) max_early = SSL_get_max_early_data(conn->xprt_ctx); else { @@ -5511,17 +5499,18 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl max_early = 0; } - if (try + conn->tmp_early_data > max_early) { - try -= (try + conn->tmp_early_data) - max_early; + if (try + conn->sent_early_data > max_early) { + try -= (try + conn->sent_early_data) - max_early; if (try <= 0) { - conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN; + if (!(conn->flags & CO_FL_EARLY_SSL_HS)) + conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN; break; } } ret = SSL_write_early_data(conn->xprt_ctx, bo_ptr(buf), try, &written_data); if (ret == 1) { ret = written_data; - conn->tmp_early_data += ret; + conn->sent_early_data += ret; if (objt_server(conn->target)) { conn->flags &= ~CO_FL_EARLY_SSL_HS; conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;