From 400de0e64746cc4da4bdd76f4896dd630eff1486 Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Mallo Date: Sat, 17 Feb 2024 13:00:52 +0100 Subject: Handle errors in SSL_read() and SSL_write() We cannot rely on the return value and the errno, the function SSL_get_error() must be used to determine what happen and if we need to retry again. A wrapper function translates the SSL error into a proper errno value. In the case a premature EOF is sent by the server, the error queue is emptied before the error is returned. Fixes: https://github.com/dillo-browser/dillo/issues/79 --- src/IO/tls_openssl.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) (limited to 'src/IO/tls_openssl.c') diff --git a/src/IO/tls_openssl.c b/src/IO/tls_openssl.c index 2da100fc..d103dcad 100644 --- a/src/IO/tls_openssl.c +++ b/src/IO/tls_openssl.c @@ -1248,13 +1248,50 @@ void a_Tls_openssl_connect(int fd, const DilloUrl *url) } } +/* + * Traduces an SSL I/O error into something understandable by IO.c + * + * Returns: -1 if there is an error and sets errno to the appropriate error, + * otherwise return the number of bytes read/written (which may be 0). + */ +static int Tls_handle_error(SSL *ssl, int ret, const char *where) +{ + int err1_ret = SSL_get_error(ssl, ret); + if (err1_ret == SSL_ERROR_NONE) { + errno = 0; + return ret; + } else if (err1_ret == SSL_ERROR_WANT_READ || err1_ret == SSL_ERROR_WANT_WRITE) { + errno = EAGAIN; + return -1; + } else if (err1_ret == SSL_ERROR_SYSCALL) { + MSG("%s failed: SSL_ERROR_SYSCALL\n", where); + errno = EPROTO; + return -1; + } else if (err1_ret == SSL_ERROR_SSL) { + unsigned long err2_ret = ERR_get_error(); + if (err2_ret) { + do { + MSG("%s failed: %s\n", where, ERR_error_string(err2_ret, NULL)); + } while ((err2_ret = ERR_get_error())); + } else { + MSG("%s failed: SSL_ERROR_SSL\n", where); + } + errno = EPROTO; + return -1; + } + + MSG("%s failed: SSL_get_error() returned %d\n", where, err1_ret); + errno = EPROTO; + return -1; +} + /* * Read data from an open TLS connection. */ int a_Tls_openssl_read(void *conn, void *buf, size_t len) { Conn_t *c = (Conn_t*)conn; - return SSL_read(c->ssl, buf, len); + return Tls_handle_error(c->ssl, SSL_read(c->ssl, buf, len), "SSL_read()"); } /* @@ -1263,7 +1300,7 @@ int a_Tls_openssl_read(void *conn, void *buf, size_t len) int a_Tls_openssl_write(void *conn, void *buf, size_t len) { Conn_t *c = (Conn_t*)conn; - return SSL_write(c->ssl, buf, len); + return Tls_handle_error(c->ssl, SSL_write(c->ssl, buf, len), "SSL_write()"); } void a_Tls_openssl_close_by_fd(int fd) -- cgit v1.2.3