diff options
author | Rodrigo Arias Mallo <rodarima@gmail.com> | 2024-02-17 13:00:52 +0100 |
---|---|---|
committer | Rodrigo Arias Mallo <rodarima@gmail.com> | 2024-02-18 10:17:45 +0100 |
commit | 400de0e64746cc4da4bdd76f4896dd630eff1486 (patch) | |
tree | 9c7f770cfa48c0f8128a0fe96e799547d96df120 /src/IO | |
parent | be1563b474d26241d2a14b27404312eacbeeeb9b (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
Diffstat (limited to 'src/IO')
-rw-r--r-- | src/IO/tls_openssl.c | 41 |
1 files changed, 39 insertions, 2 deletions
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) |