aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRodrigo Arias Mallo <rodarima@gmail.com>2024-02-17 13:00:52 +0100
committerRodrigo Arias Mallo <rodarima@gmail.com>2024-02-18 10:17:45 +0100
commit400de0e64746cc4da4bdd76f4896dd630eff1486 (patch)
tree9c7f770cfa48c0f8128a0fe96e799547d96df120
parentbe1563b474d26241d2a14b27404312eacbeeeb9b (diff)
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
-rw-r--r--ChangeLog1
-rw-r--r--src/IO/tls_openssl.c41
2 files changed, 40 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 202990b9..8a8e09cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -56,6 +56,7 @@ dillo-3.1 [not released yet]
from 16 to 20 pixels to improve usability.
- Switch tabs using the mouse wheel by default. Use the new option
scroll_switches_tabs to disable the behavior.
+ - Fix OpenSSL handling of unexpected EOF without close notify alert.
Patches: Rodrigo Arias Mallo <rodarima@gmail.com>
-----------------------------------------------------------------------------
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
@@ -1249,12 +1249,49 @@ 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)