aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ext/openssl/ossl_ssl.c20
-rw-r--r--test/test_ssl.rb24
2 files changed, 44 insertions, 0 deletions
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index eef7dbec..fae4c66a 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -1525,6 +1525,9 @@ ossl_start_ssl(VALUE self, int (*func)(), 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);
@@ -1558,6 +1561,23 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
case SSL_ERROR_SYSCALL:
if (errno) rb_sys_fail(funcname);
ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
+#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 state=%s: %s (%s)",
+ funcname, ret2, errno, SSL_state_string_long(ssl),
+ err_msg, verify_msg);
+ }
+#endif
default:
ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
}
diff --git a/test/test_ssl.rb b/test/test_ssl.rb
index 8d74f25f..2b6d9291 100644
--- a/test/test_ssl.rb
+++ b/test/test_ssl.rb
@@ -749,6 +749,30 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
+ def test_connect_certificate_verify_failed_exception_message
+ start_server(ignore_listener_error: true) { |server, port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params
+ assert_raise_with_message(OpenSSL::SSL::SSLError, /self signed/) {
+ server_connect(port, ctx)
+ }
+ }
+
+ ctx_proc = proc { |ctx|
+ ctx.cert = issue_cert(@svr, @svr_key, 30, [], @ca_cert, @ca_key,
+ not_before: Time.now-100, not_after: Time.now-10)
+ }
+ start_server(ignore_listener_error: true, ctx_proc: ctx_proc) { |server, port|
+ store = OpenSSL::X509::Store.new
+ store.add_cert(@ca_cert)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.set_params(cert_store: store)
+ assert_raise_with_message(OpenSSL::SSL::SSLError, /expired/) {
+ server_connect(port, ctx)
+ }
+ }
+ end
+
def test_multibyte_read_write
#German a umlaut
auml = [%w{ C3 A4 }.join('')].pack('H*')