Skip to content

Commit 035a04e

Browse files
authored
Merge pull request #350 from rhenium/ky/ssl-fix-verify-hostname-set-error-code
ssl: set verify error code in the case of verify_hostname failure
2 parents 65ea09c + 74ef8c0 commit 035a04e

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

ext/openssl/ossl_ssl.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,14 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
350350
rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
351351
return 0;
352352
}
353-
preverify_ok = ret == Qtrue;
353+
if (ret != Qtrue) {
354+
preverify_ok = 0;
355+
#if defined(X509_V_ERR_HOSTNAME_MISMATCH)
356+
X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH);
357+
#else
358+
X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
359+
#endif
360+
}
354361
}
355362

356363
return ossl_verify_cb_call(cb, preverify_ok, ctx);

test/test_ssl.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,46 @@ def test_verify_hostname_on_connect
752752
end
753753
end
754754

755+
def test_verify_hostname_failure_error_code
756+
ctx_proc = proc { |ctx|
757+
exts = [
758+
["keyUsage", "keyEncipherment,digitalSignature", true],
759+
["subjectAltName", "DNS:a.example.com"],
760+
]
761+
ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
762+
ctx.key = @svr_key
763+
}
764+
765+
start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port|
766+
verify_callback_ok = verify_callback_err = nil
767+
768+
ctx = OpenSSL::SSL::SSLContext.new
769+
ctx.verify_hostname = true
770+
ctx.cert_store = OpenSSL::X509::Store.new
771+
ctx.cert_store.add_cert(@ca_cert)
772+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
773+
ctx.verify_callback = -> (preverify_ok, store_ctx) {
774+
verify_callback_ok = preverify_ok
775+
verify_callback_err = store_ctx.error
776+
preverify_ok
777+
}
778+
779+
begin
780+
sock = TCPSocket.new("127.0.0.1", port)
781+
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
782+
ssl.hostname = "b.example.com"
783+
assert_handshake_error { ssl.connect }
784+
assert_equal false, verify_callback_ok
785+
code_expected = openssl?(1, 0, 2) || defined?(OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH) ?
786+
OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH :
787+
OpenSSL::X509::V_ERR_CERT_REJECTED
788+
assert_equal code_expected, verify_callback_err
789+
ensure
790+
sock&.close
791+
end
792+
end
793+
end
794+
755795
def test_unset_OP_ALL
756796
ctx_proc = Proc.new { |ctx|
757797
# If OP_DONT_INSERT_EMPTY_FRAGMENTS is not defined, this test is

0 commit comments

Comments
 (0)