diff options
-rw-r--r-- | src/plugins/tlsopenssl/tls_openssl.c | 34 | ||||
-rw-r--r-- | src/vnet/tls/tls.c | 10 | ||||
-rw-r--r-- | src/vnet/tls/tls.h | 1 |
3 files changed, 42 insertions, 3 deletions
diff --git a/src/plugins/tlsopenssl/tls_openssl.c b/src/plugins/tlsopenssl/tls_openssl.c index 2befac0dc28..74b8142a68d 100644 --- a/src/plugins/tlsopenssl/tls_openssl.c +++ b/src/plugins/tlsopenssl/tls_openssl.c @@ -155,6 +155,10 @@ openssl_lctx_get (u32 lctx_index) return pool_elt_at_index (openssl_main.lctx_pool, lctx_index); } +#define ossl_check_err_is_fatal(_ssl, _rv) \ + if (PREDICT_FALSE (_rv < 0 && SSL_get_error (_ssl, _rv) == SSL_ERROR_SSL)) \ + return -1; + static int openssl_read_from_ssl_into_fifo (svm_fifo_t * f, SSL * ssl) { @@ -174,7 +178,10 @@ openssl_read_from_ssl_into_fifo (svm_fifo_t * f, SSL * ssl) /* Return early if we can't read anything */ read = SSL_read (ssl, fs[0].data, fs[0].len); if (read <= 0) - return 0; + { + ossl_check_err_is_fatal (ssl, read); + return 0; + } for (i = 1; i < n_fs; i++) { @@ -182,7 +189,10 @@ openssl_read_from_ssl_into_fifo (svm_fifo_t * f, SSL * ssl) read += rv > 0 ? rv : 0; if (rv < (int) fs[i].len) - break; + { + ossl_check_err_is_fatal (ssl, rv); + break; + } } svm_fifo_enqueue_nocopy (f, read); @@ -206,7 +216,10 @@ openssl_write_from_fifo_into_ssl (svm_fifo_t *f, SSL *ssl, u32 max_len) rv = SSL_write (ssl, fs[i].data, fs[i].len); wrote += (rv > 0) ? rv : 0; if (rv < (int) fs[i].len) - break; + { + ossl_check_err_is_fatal (ssl, rv); + break; + } i++; } @@ -402,6 +415,14 @@ openssl_ctx_write_tls (tls_ctx_t *ctx, session_t *app_session, goto check_tls_fifo; wrote = openssl_write_from_fifo_into_ssl (f, oc->ssl, deq_max); + + /* Unrecoverable protocol error. Reset connection */ + if (PREDICT_FALSE (wrote < 0)) + { + tls_notify_app_io_error (ctx); + return 0; + } + if (!wrote) goto check_tls_fifo; @@ -518,6 +539,13 @@ openssl_ctx_read_tls (tls_ctx_t *ctx, session_t *tls_session) read = openssl_read_from_ssl_into_fifo (f, oc->ssl); + /* Unrecoverable protocol error. Reset connection */ + if (PREDICT_FALSE (read < 0)) + { + tls_notify_app_io_error (ctx); + return 0; + } + /* If handshake just completed, session may still be in accepting state */ if (read && app_session->session_state >= SESSION_STATE_READY) tls_notify_app_enqueue (ctx, app_session); diff --git a/src/vnet/tls/tls.c b/src/vnet/tls/tls.c index b91282ce074..54bb739e11d 100644 --- a/src/vnet/tls/tls.c +++ b/src/vnet/tls/tls.c @@ -400,6 +400,16 @@ tls_ctx_handshake_is_over (tls_ctx_t * ctx) } void +tls_notify_app_io_error (tls_ctx_t *ctx) +{ + ASSERT (tls_ctx_handshake_is_over (ctx)); + + session_transport_reset_notify (&ctx->connection); + session_transport_closed_notify (&ctx->connection); + tls_disconnect_transport (ctx); +} + +void tls_session_reset_callback (session_t * s) { tls_ctx_t *ctx; diff --git a/src/vnet/tls/tls.h b/src/vnet/tls/tls.h index 4e2fabd5669..54798e0230f 100644 --- a/src/vnet/tls/tls.h +++ b/src/vnet/tls/tls.h @@ -137,6 +137,7 @@ int tls_add_vpp_q_builtin_rx_evt (session_t * s); int tls_notify_app_accept (tls_ctx_t * ctx); int tls_notify_app_connected (tls_ctx_t * ctx, session_error_t err); void tls_notify_app_enqueue (tls_ctx_t * ctx, session_t * app_session); +void tls_notify_app_io_error (tls_ctx_t *ctx); void tls_disconnect_transport (tls_ctx_t * ctx); #endif /* SRC_VNET_TLS_TLS_H_ */ |