diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2023-06-07 16:01:01 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2023-06-07 16:14:56 +0900 |
commit | 5113777e82716dbbfe294d8b65daca2535c0dc1f (patch) | |
tree | 14438642d554c97236c66f6ba753d05c090409ea | |
parent | 10833aa8f606d5c927e6dfd4bca8e86cb1678843 (diff) | |
download | ruby-openssl-5113777e82716dbbfe294d8b65daca2535c0dc1f.tar.gz |
ssl: adjust "certificate verify failed" error on SSL_ERROR_SYSCALL
Enrich SSLError's message with the low-level certificate verification
result, even if SSL_get_error() returns SSL_ERROR_SYSCALL. This is
currently done on SSL_ERROR_SSL only.
According to the man page of SSL_get_error(), SSL_ERROR_SYSCALL may be
returned for "other errors, check the error queue for details". This
apparently means we have to treat SSL_ERROR_SYSCALL, if errno is not
set, as equivalent to SSL_ERROR_SSL.
-rw-r--r-- | ext/openssl/ossl_ssl.c | 50 |
1 files changed, 25 insertions, 25 deletions
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 9af6c021..5baba736 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1756,9 +1756,6 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts) int ret, ret2; VALUE cb_state; int nonblock = opts != Qfalse; -#if defined(SSL_R_CERTIFICATE_VERIFY_FAILED) - unsigned long err; -#endif rb_ivar_set(self, ID_callback_state, Qnil); @@ -1796,30 +1793,33 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts) continue; #endif if (errno) rb_sys_fail(funcname); - ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s", - funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl)); - + /* fallthrough */ + default: { + VALUE error_append = Qnil; #if defined(SSL_R_CERTIFICATE_VERIFY_FAILED) - case SSL_ERROR_SSL: - err = ERR_peek_last_error(); - if (ERR_GET_LIB(err) == ERR_LIB_SSL && - ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) { - const char *err_msg = ERR_reason_error_string(err), - *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl)); - if (!err_msg) - err_msg = "(null)"; - if (!verify_msg) - verify_msg = "(null)"; - ossl_clear_error(); /* let ossl_raise() not append message */ - ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s: %s (%s)", - funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl), - err_msg, verify_msg); - } + unsigned long err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_SSL && + ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) { + const char *err_msg = ERR_reason_error_string(err), + *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl)); + if (!err_msg) + err_msg = "(null)"; + if (!verify_msg) + verify_msg = "(null)"; + ossl_clear_error(); /* let ossl_raise() not append message */ + error_append = rb_sprintf(": %s (%s)", err_msg, verify_msg); + } #endif - /* fallthrough */ - default: - ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s", - funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl)); + ossl_raise(eSSLError, + "%s%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s%"PRIsVALUE, + funcname, + ret2 == SSL_ERROR_SYSCALL ? " SYSCALL" : "", + ret2, + errno, + peeraddr_ip_str(self), + SSL_state_string_long(ssl), + error_append); + } } } |