diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2017-01-26 13:35:09 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2017-01-26 13:35:09 +0900 |
commit | 7b0ae4541c66ce228ba4abd75c8f35be177dc8f8 (patch) | |
tree | cbcc75d18cb364e16a2ebd63348498721a1c99a2 | |
parent | bb0d1aff173b53d79dd09477106a650db6aecccb (diff) | |
parent | 654e024beec5a4f6deb05c8c7994544aabd1e825 (diff) | |
download | ruby-openssl-7b0ae4541c66ce228ba4abd75c8f35be177dc8f8.tar.gz |
Merge branch 'topic/ssl-certificate-verify-error-desc'
* topic/ssl-certificate-verify-error-desc:
ssl: show reason of 'certificate verify error' in exception message
Make exceptions with the same format regardless of OpenSSL.debug
-rw-r--r-- | ext/openssl/ossl.c | 13 | ||||
-rw-r--r-- | ext/openssl/ossl_ssl.c | 20 | ||||
-rw-r--r-- | test/test_ssl.rb | 24 |
3 files changed, 49 insertions, 8 deletions
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 1a0da90c..bcadc3e1 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -260,18 +260,15 @@ static VALUE ossl_make_error(VALUE exc, const char *fmt, va_list args) { VALUE str = Qnil; - const char *msg; - long e; + unsigned long e; - e = ERR_peek_last_error(); if (fmt) { str = rb_vsprintf(fmt, args); } + e = ERR_peek_last_error(); if (e) { - if (dOSSL == Qtrue) /* FULL INFO */ - msg = ERR_error_string(e, NULL); - else - msg = ERR_reason_error_string(e); + const char *msg = ERR_reason_error_string(e); + if (NIL_P(str)) { if (msg) str = rb_str_new_cstr(msg); } @@ -279,8 +276,8 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args) if (RSTRING_LEN(str)) rb_str_cat2(str, ": "); rb_str_cat2(str, msg ? msg : "(null)"); } + ossl_clear_error(); } - ossl_clear_error(); if (NIL_P(str)) str = rb_str_new(0, 0); return rb_exc_new3(exc, str); diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index ef948dc5..c0063d69 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1521,6 +1521,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); @@ -1554,6 +1557,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 b2f36c75..8bf0c214 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -745,6 +745,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*') |