aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-07-03 12:43:31 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-07-03 14:15:15 +0900
commit66c1da57eb03c19f96f3f1c843ea2a93dca3d243 (patch)
treefca71b509eb3066e50e09e2e0a5e29830b7f76f1
parent0d4456b49a7c4975bab021262561652ef3d457ce (diff)
downloadruby-openssl-66c1da57eb03c19f96f3f1c843ea2a93dca3d243.tar.gz
ssl: reject keys without private componentstopic/ssl-check-pkey-private
OpenSSL checks if the PKey's public key matches with the certificate, but does not check that the PKey contains the private components. As a result, OpenSSL does a NULL dereference while doing SSL/TLS negotiation. [Bug #8673]
-rw-r--r--ext/openssl/ossl_ssl.c4
-rw-r--r--test/test_ssl.rb20
2 files changed, 22 insertions, 2 deletions
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 7236f668..76832081 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -228,7 +228,7 @@ ossl_call_client_cert_cb(VALUE obj)
ary = rb_funcall(cb, rb_intern("call"), 1, obj);
Check_Type(ary, T_ARRAY);
GetX509CertPtr(cert = rb_ary_entry(ary, 0));
- GetPKeyPtr(key = rb_ary_entry(ary, 1));
+ GetPrivPKeyPtr(key = rb_ary_entry(ary, 1));
return rb_ary_new3(2, cert, key);
}
@@ -774,7 +774,7 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_cert(self);
cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
val = ossl_sslctx_get_key(self);
- key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */
+ key = NIL_P(val) ? NULL : GetPrivPKeyPtr(val); /* NO DUP NEEDED */
if (cert && key) {
if (!SSL_CTX_use_certificate(ctx, cert)) {
/* Adds a ref => Safe to FREE */
diff --git a/test/test_ssl.rb b/test/test_ssl.rb
index e7f3348c..fd78a217 100644
--- a/test/test_ssl.rb
+++ b/test/test_ssl.rb
@@ -236,6 +236,26 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
+ def test_client_auth_public_key
+ vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
+ start_server(vflag, true, ignore_listener_error: true) do |server, port|
+ assert_raise(ArgumentError) {
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.key = @cli_key.public_key
+ ctx.cert = @cli_cert
+ server_connect(port, ctx) { }
+ }
+
+ assert_raise(OpenSSL::SSL::SSLError) {
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.client_cert_cb = Proc.new{ |ssl|
+ [@cli_cert, @cli_key.public_key]
+ }
+ server_connect(port, ctx) { }
+ }
+ end
+ end
+
def test_client_ca
ctx_proc = Proc.new do |ctx|
ctx.client_ca = [@ca_cert]