]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix to print detailed errors when an SSL IO routine fails via
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Thu, 19 Oct 2023 09:17:32 +0000 (11:17 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Thu, 19 Oct 2023 09:17:32 +0000 (11:17 +0200)
  SSL_get_error.

daemon/remote.c
dnstap/dtstream.c
dnstap/unbound-dnstap-socket.c
doc/Changelog
testcode/dohclient.c
testcode/streamtcp.c
util/net_help.c
util/net_help.h
util/netevent.c

index 235f96c7fde683df5a03afb9abb40d59f44709c3..3eb711ce64285ad8bc960d6eaa2225e9e42e22c9 100644 (file)
@@ -523,12 +523,13 @@ ssl_print_text(RES* res, const char* text)
        if(res->ssl) {
                ERR_clear_error();
                if((r=SSL_write(res->ssl, text, (int)strlen(text))) <= 0) {
-                       if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) {
+                       int r2;
+                       if((r2=SSL_get_error(res->ssl, r)) == SSL_ERROR_ZERO_RETURN) {
                                verbose(VERB_QUERY, "warning, in SSL_write, peer "
                                        "closed connection");
                                return 0;
                        }
-                       log_crypto_err("could not SSL_write");
+                       log_crypto_err_io("could not SSL_write", r2);
                        return 0;
                }
        } else {
@@ -579,11 +580,12 @@ ssl_read_line(RES* res, char* buf, size_t max)
                if(res->ssl) {
                        ERR_clear_error();
                        if((r=SSL_read(res->ssl, buf+len, 1)) <= 0) {
-                               if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) {
+                               int r2;
+                               if((r2=SSL_get_error(res->ssl, r)) == SSL_ERROR_ZERO_RETURN) {
                                        buf[len] = 0;
                                        return 1;
                                }
-                               log_crypto_err("could not SSL_read");
+                               log_crypto_err_io("could not SSL_read", r2);
                                return 0;
                        }
                } else {
@@ -3222,9 +3224,10 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, RES* res)
        if(res->ssl) {
                ERR_clear_error();
                if((r=SSL_read(res->ssl, magic, (int)sizeof(magic)-1)) <= 0) {
-                       if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN)
+                       int r2;
+                       if((r2=SSL_get_error(res->ssl, r)) == SSL_ERROR_ZERO_RETURN)
                                return;
-                       log_crypto_err("could not SSL_read");
+                       log_crypto_err_io("could not SSL_read", r2);
                        return;
                }
        } else {
@@ -3291,7 +3294,7 @@ remote_handshake_later(struct daemon_remote* rc, struct rc_state* s,
                        log_err("remote control connection closed prematurely");
                log_addr(VERB_OPS, "failed connection from",
                        &s->c->repinfo.remote_addr, s->c->repinfo.remote_addrlen);
-               log_crypto_err("remote control failed ssl");
+               log_crypto_err_io("remote control failed ssl", r2);
                clean_point(rc, s);
        }
        return 0;
index 9153f040472d92eaa4ce7ebae23b6566f76d3beb..69c951276ff0ddc28c9359cad4b2d85c8f8e4017 100644 (file)
@@ -788,7 +788,7 @@ static int dtio_write_ssl(struct dt_io_thread* dtio, uint8_t* buf,
                        }
                        return -1;
                }
-               log_crypto_err("dnstap io, could not SSL_write");
+               log_crypto_err_io("dnstap io, could not SSL_write", want);
                return -1;
        }
        return r;
@@ -1029,7 +1029,7 @@ static int ssl_read_bytes(struct dt_io_thread* dtio, void* buf, size_t len)
                                "other side");
                        return 0;
                }
-               log_crypto_err("could not SSL_read");
+               log_crypto_err_io("could not SSL_read", want);
                verbose(VERB_DETAIL, "dnstap io: output closed by the "
                                "other side");
                return 0;
@@ -1431,8 +1431,8 @@ static int dtio_ssl_handshake(struct dt_io_thread* dtio,
                } else {
                        unsigned long err = ERR_get_error();
                        if(!squelch_err_ssl_handshake(err)) {
-                               log_crypto_err_code("dnstap io, ssl handshake failed",
-                                       err);
+                               log_crypto_err_io_code("dnstap io, ssl handshake failed",
+                                       want, err);
                                verbose(VERB_OPS, "dnstap io, ssl handshake failed "
                                        "from %s", dtio->ip_str);
                        }
index d172a6744a07395e7c7149d22d13002759daba51..04fda74b80e155dba2995abbdcff0a343738c35e 100644 (file)
@@ -708,7 +708,7 @@ static ssize_t ssl_read_bytes(struct tap_data* data, void* buf, size_t len)
                                (data->id?data->id:""));
                        return 0;
                }
-               log_crypto_err("could not SSL_read");
+               log_crypto_err_io("could not SSL_read", want);
                if(verbosity) log_info("dnstap client stream closed from %s",
                        (data->id?data->id:""));
                return 0;
@@ -760,10 +760,11 @@ static int reply_with_accept(struct tap_data* data)
        fd_set_block(data->fd);
        if(data->ssl) {
                if((r=SSL_write(data->ssl, acceptframe, len)) <= 0) {
-                       if(SSL_get_error(data->ssl, r) == SSL_ERROR_ZERO_RETURN)
+                       int r2;
+                       if((r2=SSL_get_error(data->ssl, r)) == SSL_ERROR_ZERO_RETURN)
                                log_err("SSL_write, peer closed connection");
                        else
-                               log_err("could not SSL_write");
+                               log_crypto_err_io("could not SSL_write", r2);
                        fd_set_nonblock(data->fd);
                        free(acceptframe);
                        return 0;
@@ -805,10 +806,11 @@ static int reply_with_finish(struct tap_data* data)
        if(data->ssl) {
                int r;
                if((r=SSL_write(data->ssl, finishframe, len)) <= 0) {
-                       if(SSL_get_error(data->ssl, r) == SSL_ERROR_ZERO_RETURN)
+                       int r2;
+                       if((r2=SSL_get_error(data->ssl, r)) == SSL_ERROR_ZERO_RETURN)
                                log_err("SSL_write, peer closed connection");
                        else
-                               log_err("could not SSL_write");
+                               log_crypto_err_io("could not SSL_write", r2);
                        fd_set_nonblock(data->fd);
                        free(finishframe);
                        return 0;
index b8b2ddd524e2009748396ae814598fb9b3c8b71e..33126fbc3d26638217b56766681d25676b4db192 100644 (file)
@@ -1,3 +1,7 @@
+19 October 2023: Wouter
+       - Fix to print detailed errors when an SSL IO routine fails via
+         SSL_get_error.
+
 18 October 2023: George
        - Mailing list patches from Daniel Gröber for DNS64 fallback to plain
          AAAA when no A record exists for synthesis, and minor DNS64 code
index de9f39d7d941f7d2b87182b24bba7640ca26882a..2c12a5043f65d59531bebea48d6845f70ba6e97f 100644 (file)
@@ -286,7 +286,7 @@ static ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session),
                        if(want == SSL_ERROR_ZERO_RETURN) {
                                return NGHTTP2_ERR_EOF;
                        }
-                       log_crypto_err("could not SSL_read");
+                       log_crypto_err_io("could not SSL_read", want);
                        return NGHTTP2_ERR_EOF;
                }
                return r;
@@ -317,7 +317,7 @@ static ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session),
                        if(want == SSL_ERROR_ZERO_RETURN) {
                                return NGHTTP2_ERR_CALLBACK_FAILURE;
                        }
-                       log_crypto_err("could not SSL_write");
+                       log_crypto_err_io("could not SSL_write", want);
                        return NGHTTP2_ERR_CALLBACK_FAILURE;
                }
                return r;
@@ -526,7 +526,7 @@ run(struct http2_session* h2_session, int port, int no_tls, int count, char** q)
                        r = SSL_get_error(ssl, r);
                        if(r != SSL_ERROR_WANT_READ &&
                                r != SSL_ERROR_WANT_WRITE) {
-                               log_crypto_err("could not ssl_handshake");
+                               log_crypto_err_io("could not ssl_handshake", r);
                                exit(1);
                        }
                }
index ef762c1619c3249a152fe208888f32173332ce23..037bcfd8b6a4e2ddaee540ee6d3b693a503ca6b6 100644 (file)
@@ -466,7 +466,7 @@ send_em(const char* svr, const char* pp2_client, int udp, int usessl,
                        r = SSL_get_error(ssl, r);
                        if(r != SSL_ERROR_WANT_READ &&
                                r != SSL_ERROR_WANT_WRITE) {
-                               log_crypto_err("could not ssl_handshake");
+                               log_crypto_err_io("could not ssl_handshake", r);
                                exit(1);
                        }
                }
index dec46da20e235b736c4b4c514305321a7384d869..16692b788d578a4bcbfc4df1285db65cfc091d31 100644 (file)
@@ -952,6 +952,110 @@ void log_crypto_err_code(const char* str, unsigned long err)
 #endif /* HAVE_SSL */
 }
 
+/** Print crypt erro with SSL_get_error want code and err_get_error code */
+static void log_crypto_err_io_code_arg(const char* str, int r,
+       unsigned long err, int err_present)
+{
+#ifdef HAVE_SSL
+       int print_errno = 0, print_crypto_err = 0;
+       const char* inf = NULL;
+
+       switch(r) {
+       case SSL_ERROR_NONE:
+               inf = "no error";
+               break;
+       case SSL_ERROR_ZERO_RETURN:
+               inf = "channel closed";
+               break;
+       case SSL_ERROR_WANT_READ:
+               inf = "want read";
+               break;
+       case SSL_ERROR_WANT_WRITE:
+               inf = "want write";
+               break;
+       case SSL_ERROR_WANT_CONNECT:
+               inf = "want connect";
+               break;
+       case SSL_ERROR_WANT_ACCEPT:
+               inf = "want accept";
+               break;
+       case SSL_ERROR_WANT_X509_LOOKUP:
+               inf = "want X509 lookup";
+               break;
+       case SSL_ERROR_WANT_ASYNC:
+               inf = "want async";
+               break;
+       case SSL_ERROR_WANT_ASYNC_JOB:
+               inf = "want async job";
+               break;
+       case SSL_ERROR_WANT_CLIENT_HELLO_CB:
+               inf = "want client hello cb";
+               break;
+       case SSL_ERROR_SYSCALL:
+               print_errno = 1;
+               inf = "syscall";
+               break;
+       case SSL_ERROR_SSL:
+               print_crypto_err = 1;
+               inf = "SSL, usually protocol, error";
+               break;
+       default:
+               inf = "unknown SSL_get_error result code";
+               print_errno = 1;
+               print_crypto_err = 1;
+       }
+       if(print_crypto_err) {
+               if(print_errno) {
+                       char buf[1024];
+                       snprintf(buf, sizeof(buf), "%s with errno %s",
+                               str, strerror(errno));
+                       if(err_present)
+                               log_crypto_err_code(buf, err);
+                       else    log_crypto_err(buf);
+               } else {
+                       if(err_present)
+                               log_crypto_err_code(str, err);
+                       else    log_crypto_err(str);
+               }
+       } else {
+               if(print_errno) {
+                       if(errno == 0)
+                               log_err("str: syscall error with errno %s",
+                                       strerror(errno));
+                       else log_err("str: %s", strerror(errno));
+               } else {
+                       log_err("str: %s", inf);
+               }
+       }
+#else
+       (void)str;
+       (void)r;
+       (void)err;
+       (void)err_present;
+#endif /* HAVE_SSL */
+}
+
+void log_crypto_err_io(const char* str, int r)
+{
+#ifdef HAVE_SSL
+       log_crypto_err_io_code_arg(str, r, 0, 0);
+#else
+       (void)str;
+       (void)r;
+#endif /* HAVE_SSL */
+}
+
+void log_crypto_err_io_code(const char* str, int r, unsigned long err)
+{
+#ifdef HAVE_SSL
+       log_crypto_err_io_code_arg(str, r, err, 1);
+#else
+       (void)str;
+       (void)r;
+       (void)err;
+#endif /* HAVE_SSL */
+}
+
 #ifdef HAVE_SSL
 /** log certificate details */
 void
index a9de910d5461652b957a14238d5f5faee3041db2..edaea42353d480afe887550c87be39f5338e2387 100644 (file)
@@ -429,6 +429,24 @@ void log_crypto_err(const char* str);
  */
 void log_crypto_err_code(const char* str, unsigned long err);
 
+/**
+ * Log an error from libcrypto that came from SSL_write and so on, with
+ * a value from SSL_get_error, calls log_err. If that fails it logs with
+ * log_crypto_err.
+ * @param str: what failed
+ * @param r: output of SSL_get_error on the I/O operation result.
+ */
+void log_crypto_err_io(const char* str, int r);
+
+/**
+ * Log an error from libcrypt that came from an I/O routine with the
+ * errcode from ERR_get_error. Calls log_err() and log_crypto_err_code.
+ * @param str: what failed
+ * @param r: output of SSL_get_error on the I/O operation result.
+ * @param err: error code from ERR_get_error
+ */
+void log_crypto_err_io_code(const char* str, int r, unsigned long err);
+
 /**
  * Log certificate details verbosity, string, of X509 cert
  * @param level: verbosity level
index 0a45f22ede5819731e31c98bbb00bad3df88a0e7..c26b13e4a6852d5ff487d1da80e294ef34de9ff3 100644 (file)
@@ -1666,7 +1666,8 @@ ssl_handshake(struct comm_point* c)
                } else {
                        unsigned long err = ERR_get_error();
                        if(!squelch_err_ssl_handshake(err)) {
-                               log_crypto_err_code("ssl handshake failed", err);
+                               log_crypto_err_io_code("ssl handshake failed",
+                                       want, err);
                                log_addr(VERB_OPS, "ssl handshake failed",
                                        &c->repinfo.remote_addr,
                                        c->repinfo.remote_addrlen);
@@ -1816,7 +1817,8 @@ ssl_handle_read(struct comm_point* c)
                                                                strerror(errno));
                                                return 0;
                                        }
-                                       log_crypto_err("could not SSL_read");
+                                       log_crypto_err_io("could not SSL_read",
+                                               want);
                                        return 0;
                                }
                                c->tcp_byte_count += r;
@@ -1883,7 +1885,8 @@ ssl_handle_read(struct comm_point* c)
                                                                strerror(errno));
                                                return 0;
                                        }
-                                       log_crypto_err("could not SSL_read");
+                                       log_crypto_err_io("could not SSL_read",
+                                               want);
                                        return 0;
                                }
                                c->tcp_byte_count += r;
@@ -1943,7 +1946,7 @@ ssl_handle_read(struct comm_point* c)
                                                strerror(errno));
                                return 0;
                        }
-                       log_crypto_err("could not SSL_read");
+                       log_crypto_err_io("could not SSL_read", want);
                        return 0;
                }
                c->tcp_byte_count += r;
@@ -1993,7 +1996,7 @@ ssl_handle_read(struct comm_point* c)
                                                strerror(errno));
                                return 0;
                        }
-                       log_crypto_err("could not SSL_read");
+                       log_crypto_err_io("could not SSL_read", want);
                        return 0;
                }
                sldns_buffer_skip(c->buffer, (ssize_t)r);
@@ -2084,7 +2087,7 @@ ssl_handle_write(struct comm_point* c)
                                                strerror(errno));
                                return 0;
                        }
-                       log_crypto_err("could not SSL_write");
+                       log_crypto_err_io("could not SSL_write", want);
                        return 0;
                }
                if(c->tcp_write_and_read) {
@@ -2136,7 +2139,7 @@ ssl_handle_write(struct comm_point* c)
                                        strerror(errno));
                        return 0;
                }
-               log_crypto_err("could not SSL_write");
+               log_crypto_err_io("could not SSL_write", want);
                return 0;
        }
        if(c->tcp_write_and_read) {
@@ -2930,7 +2933,7 @@ ssl_http_read_more(struct comm_point* c)
                                        strerror(errno));
                        return 0;
                }
-               log_crypto_err("could not SSL_read");
+               log_crypto_err_io("could not SSL_read", want);
                return 0;
        }
        verbose(VERB_ALGO, "ssl http read more skip to %d + %d",
@@ -3381,7 +3384,7 @@ ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session), uint8_t* buf,
                                                strerror(errno));
                                return NGHTTP2_ERR_CALLBACK_FAILURE;
                        }
-                       log_crypto_err("could not SSL_read");
+                       log_crypto_err_io("could not SSL_read", want);
                        return NGHTTP2_ERR_CALLBACK_FAILURE;
                }
                return r;
@@ -3636,7 +3639,7 @@ ssl_http_write_more(struct comm_point* c)
                                        strerror(errno));
                        return 0;
                }
-               log_crypto_err("could not SSL_write");
+               log_crypto_err_io("could not SSL_write", want);
                return 0;
        }
        sldns_buffer_skip(c->buffer, (ssize_t)r);
@@ -3709,7 +3712,7 @@ ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session), const uint8_t* buf,
                                                strerror(errno));
                                return NGHTTP2_ERR_CALLBACK_FAILURE;
                        }
-                       log_crypto_err("could not SSL_write");
+                       log_crypto_err_io("could not SSL_write", want);
                        return NGHTTP2_ERR_CALLBACK_FAILURE;
                }
                return r;