Index: test/openssl/test_x509store.rb =================================================================== --- test/openssl/test_x509store.rb (.../ruby_1_8_7/test/openssl) (revision 27451) +++ test/openssl/test_x509store.rb (.../ruby_1_8/test/openssl) (revision 27451) @@ -4,6 +4,7 @@ rescue LoadError end require "test/unit" +require "tempfile" if defined?(OpenSSL) @@ -198,7 +199,7 @@ nil, nil, OpenSSL::Digest::SHA1.new) store = OpenSSL::X509::Store.new store.add_cert(ca1_cert) - assert_raises(OpenSSL::X509::StoreError){ + assert_raise(OpenSSL::X509::StoreError){ store.add_cert(ca1_cert) # add same certificate twice } @@ -209,10 +210,37 @@ crl2 = issue_crl(revoke_info, 2, now+1800, now+3600, [], ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new) store.add_crl(crl1) - assert_raises(OpenSSL::X509::StoreError){ + assert_raise(OpenSSL::X509::StoreError){ store.add_crl(crl2) # add CRL issued by same CA twice. } end + + def test_add_file + ca1_cert = < e + # OpenSSL 1.0.0 added checks for pkey OID + assert_equal('wrong public key type', e.message) + end + + begin + assert_equal(false, cert_dsa.verify(@rsa1024)) + rescue OpenSSL::X509::CertificateError => e + # OpenSSL 1.0.0 added checks for pkey OID + assert_equal('wrong public key type', e.message) + end + end + def test_sign_and_verify cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [], - nil, nil, OpenSSL::Digest::SHA1.new) + nil, nil, OpenSSL::Digest::SHA1.new) assert_equal(false, cert.verify(@rsa1024)) assert_equal(true, cert.verify(@rsa2048)) - assert_equal(false, cert.verify(@dsa256)) - assert_equal(false, cert.verify(@dsa512)) cert.serial = 2 assert_equal(false, cert.verify(@rsa2048)) cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [], - nil, nil, OpenSSL::Digest::MD5.new) + nil, nil, OpenSSL::Digest::MD5.new) assert_equal(false, cert.verify(@rsa1024)) assert_equal(true, cert.verify(@rsa2048)) - assert_equal(false, cert.verify(@dsa256)) - assert_equal(false, cert.verify(@dsa512)) cert.subject = @ee1 assert_equal(false, cert.verify(@rsa2048)) cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [], - nil, nil, OpenSSL::Digest::DSS1.new) - assert_equal(false, cert.verify(@rsa1024)) - assert_equal(false, cert.verify(@rsa2048)) + nil, nil, OpenSSL::Digest::DSS1.new) assert_equal(false, cert.verify(@dsa256)) assert_equal(true, cert.verify(@dsa512)) - cert.not_after = Time.now + cert.not_after = Time.now assert_equal(false, cert.verify(@dsa512)) + end - assert_raises(OpenSSL::X509::CertificateError){ + def test_dsig_algorithm_mismatch + assert_raise(OpenSSL::X509::CertificateError) do cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [], - nil, nil, OpenSSL::Digest::DSS1.new) - } - assert_raises(OpenSSL::X509::CertificateError){ + nil, nil, OpenSSL::Digest::DSS1.new) + end + assert_raise(OpenSSL::X509::CertificateError) do cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [], - nil, nil, OpenSSL::Digest::MD5.new) - } - assert_raises(OpenSSL::X509::CertificateError){ - cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [], - nil, nil, OpenSSL::Digest::SHA1.new) - } + nil, nil, OpenSSL::Digest::MD5.new) + end end + + def test_dsa_with_sha2 + begin + cert = issue_cert(@ca, @dsa256, 1, Time.now, Time.now+3600, [], + nil, nil, OpenSSL::Digest::SHA256.new) + assert_equal("dsa_with_SHA256", cert.signature_algorithm) + rescue OpenSSL::X509::CertificateError + # dsa_with_sha2 not supported. skip following test. + return + end + # TODO: need more tests for dsa + sha2 + + # SHA1 is allowed from OpenSSL 1.0.0 (0.9.8 requireds DSS1) + cert = issue_cert(@ca, @dsa256, 1, Time.now, Time.now+3600, [], + nil, nil, OpenSSL::Digest::SHA1.new) + assert_equal("dsaWithSHA1", cert.signature_algorithm) + end + + def test_check_private_key + cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [], + nil, nil, OpenSSL::Digest::SHA1.new) + assert_equal(true, cert.check_private_key(@rsa2048)) + end + + def test_to_text + cert_pem = < e + # just an exception for longer dgst before openssl-0.9.8m + assert_equal('ECDSA_sign: data too large for key size', e.message) + # no need to do following tests + return + end + end + end + def test_dh_compute_key for key in @keys k = OpenSSL::PKey::EC.new(key.group) Index: test/openssl/test_pkcs7.rb =================================================================== --- test/openssl/test_pkcs7.rb (.../ruby_1_8_7/test/openssl) (revision 27451) +++ test/openssl/test_pkcs7.rb (.../ruby_1_8/test/openssl) (revision 27451) @@ -28,6 +28,7 @@ ["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true], ["authorityKeyIdentifier","keyid:always",false], ["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false], + ["nsCertType","client,email",false], ] @ee1_cert = issue_cert(ee1, @rsa1024, 2, Time.now, Time.now+1800, ee_exts, @ca_cert, @rsa2048, OpenSSL::Digest::SHA1.new) @@ -35,7 +36,7 @@ @ca_cert, @rsa2048, OpenSSL::Digest::SHA1.new) end - def issue_cert(*args) + def issue_cert(*args) OpenSSL::TestUtils.issue_cert(*args) end @@ -46,6 +47,127 @@ data = "aaaaa\r\nbbbbb\r\nccccc\r\n" tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs) + p7 = OpenSSL::PKCS7.new(tmp.to_der) + certs = p7.certificates + signers = p7.signers + assert(p7.verify([], store)) + assert_equal(data, p7.data) + assert_equal(2, certs.size) + assert_equal(@ee1_cert.subject.to_s, certs[0].subject.to_s) + assert_equal(@ca_cert.subject.to_s, certs[1].subject.to_s) + assert_equal(1, signers.size) + assert_equal(@ee1_cert.serial, signers[0].serial) + assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s) + + # Normaly OpenSSL tries to translate the supplied content into canonical + # MIME format (e.g. a newline character is converted into CR+LF). + # If the content is a binary, PKCS7::BINARY flag should be used. + + data = "aaaaa\nbbbbb\nccccc\n" + flag = OpenSSL::PKCS7::BINARY + tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs, flag) + p7 = OpenSSL::PKCS7.new(tmp.to_der) + certs = p7.certificates + signers = p7.signers + assert(p7.verify([], store)) + assert_equal(data, p7.data) + assert_equal(2, certs.size) + assert_equal(@ee1_cert.subject.to_s, certs[0].subject.to_s) + assert_equal(@ca_cert.subject.to_s, certs[1].subject.to_s) + assert_equal(1, signers.size) + assert_equal(@ee1_cert.serial, signers[0].serial) + assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s) + + # A signed-data which have multiple signatures can be created + # through the following steps. + # 1. create two signed-data + # 2. copy signerInfo and certificate from one to another + + tmp1 = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, [], flag) + tmp2 = OpenSSL::PKCS7.sign(@ee2_cert, @rsa1024, data, [], flag) + tmp1.add_signer(tmp2.signers[0]) + tmp1.add_certificate(@ee2_cert) + + p7 = OpenSSL::PKCS7.new(tmp1.to_der) + certs = p7.certificates + signers = p7.signers + assert(p7.verify([], store)) + assert_equal(data, p7.data) + assert_equal(2, certs.size) + assert_equal(2, signers.size) + assert_equal(@ee1_cert.serial, signers[0].serial) + assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s) + assert_equal(@ee2_cert.serial, signers[1].serial) + assert_equal(@ee2_cert.issuer.to_s, signers[1].issuer.to_s) + end + + def test_detached_sign + store = OpenSSL::X509::Store.new + store.add_cert(@ca_cert) + ca_certs = [@ca_cert] + + data = "aaaaa\nbbbbb\nccccc\n" + flag = OpenSSL::PKCS7::BINARY|OpenSSL::PKCS7::DETACHED + tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs, flag) + p7 = OpenSSL::PKCS7.new(tmp.to_der) + a1 = OpenSSL::ASN1.decode(p7) + + certs = p7.certificates + signers = p7.signers + assert(!p7.verify([], store)) + assert(p7.verify([], store, data)) + assert_equal(data, p7.data) + assert_equal(2, certs.size) + assert_equal(@ee1_cert.subject.to_s, certs[0].subject.to_s) + assert_equal(@ca_cert.subject.to_s, certs[1].subject.to_s) + assert_equal(1, signers.size) + assert_equal(@ee1_cert.serial, signers[0].serial) + assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s) + end + + def test_enveloped + if OpenSSL::OPENSSL_VERSION_NUMBER <= 0x0090704f + # PKCS7_encrypt() of OpenSSL-0.9.7d goes to SEGV. + # http://www.mail-archive.com/openssl-dev@openssl.org/msg17376.html + return + end + + certs = [@ee1_cert, @ee2_cert] + cipher = OpenSSL::Cipher::AES.new("128-CBC") + data = "aaaaa\nbbbbb\nccccc\n" + + tmp = OpenSSL::PKCS7.encrypt(certs, data, cipher, OpenSSL::PKCS7::BINARY) + p7 = OpenSSL::PKCS7.new(tmp.to_der) + recip = p7.recipients + assert_equal(:enveloped, p7.type) + assert_equal(2, recip.size) + + assert_equal(@ca_cert.subject.to_s, recip[0].issuer.to_s) + assert_equal(2, recip[0].serial) + assert_equal(data, p7.decrypt(@rsa1024, @ee1_cert)) + + assert_equal(@ca_cert.subject.to_s, recip[1].issuer.to_s) + assert_equal(3, recip[1].serial) + assert_equal(data, p7.decrypt(@rsa1024, @ee2_cert)) + end + + def silent + begin + back, $VERBOSE = $VERBOSE, nil + yield + ensure + $VERBOSE = back if back + end + end + + def test_signed_pkcs7_pkcs7 + silent do + store = OpenSSL::X509::Store.new + store.add_cert(@ca_cert) + ca_certs = [@ca_cert] + + data = "aaaaa\r\nbbbbb\r\nccccc\r\n" + tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs) p7 = OpenSSL::PKCS7::PKCS7.new(tmp.to_der) certs = p7.certificates signers = p7.signers @@ -77,7 +199,7 @@ assert_equal(@ee1_cert.serial, signers[0].serial) assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s) - # A signed-data which have multiple signatures can be created + # A signed-data which have multiple signatures can be created # through the following steps. # 1. create two signed-data # 2. copy signerInfo and certificate from one to another @@ -85,7 +207,7 @@ tmp1 = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, [], flag) tmp2 = OpenSSL::PKCS7.sign(@ee2_cert, @rsa1024, data, [], flag) tmp1.add_signer(tmp2.signers[0]) - tmp1.add_certificate(@ee2_cert) + tmp1.add_certificate(@ee2_cert) p7 = OpenSSL::PKCS7::PKCS7.new(tmp1.to_der) certs = p7.certificates @@ -99,8 +221,10 @@ assert_equal(@ee2_cert.serial, signers[1].serial) assert_equal(@ee2_cert.issuer.to_s, signers[1].issuer.to_s) end + end - def test_detached_sign + def test_detached_sign_pkcs7_pkcs7 + silent do store = OpenSSL::X509::Store.new store.add_cert(@ca_cert) ca_certs = [@ca_cert] @@ -123,8 +247,10 @@ assert_equal(@ee1_cert.serial, signers[0].serial) assert_equal(@ee1_cert.issuer.to_s, signers[0].issuer.to_s) end + end - def test_enveloped + def test_enveloped_pkcs7_pkcs7 + silent do if OpenSSL::OPENSSL_VERSION_NUMBER <= 0x0090704f # PKCS7_encrypt() of OpenSSL-0.9.7d goes to SEGV. # http://www.mail-archive.com/openssl-dev@openssl.org/msg17376.html @@ -149,6 +275,7 @@ assert_equal(3, recip[1].serial) assert_equal(data, p7.decrypt(@rsa1024, @ee2_cert)) end + end end end Index: test/openssl/ssl_server.rb =================================================================== --- test/openssl/ssl_server.rb (.../ruby_1_8_7/test/openssl) (revision 27451) +++ test/openssl/ssl_server.rb (.../ruby_1_8/test/openssl) (revision 27451) @@ -53,7 +53,7 @@ port = port + i break rescue Errno::EADDRINUSE - next + next end } ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) Index: test/openssl/utils.rb =================================================================== --- test/openssl/utils.rb (.../ruby_1_8_7/test/openssl) (revision 27451) +++ test/openssl/utils.rb (.../ruby_1_8/test/openssl) (revision 27451) @@ -96,16 +96,16 @@ cert end - def issue_crl(revoke_info, serial, lastup, nextup, extensions, + def issue_crl(revoke_info, serial, lastup, nextup, extensions, issuer, issuer_key, digest) crl = OpenSSL::X509::CRL.new crl.issuer = issuer.subject crl.version = 1 crl.last_update = lastup crl.next_update = nextup - revoke_info.each{|serial, time, reason_code| + revoke_info.each{|rserial, time, reason_code| revoked = OpenSSL::X509::Revoked.new - revoked.serial = serial + revoked.serial = rserial revoked.time = time enum = OpenSSL::ASN1::Enumerated(reason_code) ext = OpenSSL::X509::Extension.new("CRLReason", enum) Index: test/openssl/test_ssl.rb =================================================================== --- test/openssl/test_ssl.rb (.../ruby_1_8_7/test/openssl) (revision 27451) +++ test/openssl/test_ssl.rb (.../ruby_1_8/test/openssl) (revision 27451) @@ -6,6 +6,8 @@ require "rbconfig" require "socket" require "test/unit" +require 'tempfile' + begin loadpath = $:.dup $:.replace($: | [File.expand_path("../ruby", File.dirname(__FILE__))]) @@ -58,6 +60,20 @@ OpenSSL::TestUtils.issue_crl(*arg) end + def choose_port(port) + tcps = nil + 100.times{ |i| + begin + tcps = TCPServer.new("127.0.0.1", port+i) + port = port + i + break + rescue Errno::EADDRINUSE + next + end + } + return tcps, port + end + def readwrite_loop(ctx, ssl) while line = ssl.gets if line =~ /^STARTTLS$/ @@ -78,22 +94,22 @@ begin ssl = ssls.accept rescue OpenSSL::SSL::SSLError - retry + retry end Thread.start do - Thread.current.abort_on_exception = true + Thread.current.abort_on_exception = true server_proc.call(ctx, ssl) end end - rescue Errno::EBADF, IOError + rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED end def start_server(port0, verify_mode, start_immediately, args = {}, &block) ctx_proc = args[:ctx_proc] server_proc = args[:server_proc] server_proc ||= method(:readwrite_loop) - + store = OpenSSL::X509::Store.new store.add_cert(@ca_cert) store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT @@ -106,8 +122,7 @@ ctx_proc.call(ctx) if ctx_proc Socket.do_not_reverse_lookup = true - tcps = nil - port = port0 + tcps, port = choose_port(port0) begin tcps = TCPServer.new("127.0.0.1", port) rescue Errno::EADDRINUSE @@ -120,22 +135,33 @@ begin server = Thread.new do - Thread.current.abort_on_exception = true + Thread.current.abort_on_exception = true server_loop(ctx, ssls, server_proc) end - $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, pid, port) if $DEBUG + $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, $$, port) if $DEBUG block.call(server, port.to_i) ensure - tcps.close if (tcps) - if (server) - server.join(5) - if server.alive? - server.kill - server.join - flunk("TCPServer was closed and SSLServer is still alive") unless $! + begin + begin + tcps.shutdown + rescue Errno::ENOTCONN + # when `Errno::ENOTCONN: Socket is not connected' on some platforms, + # call #close instead of #shutdown. + tcps.close + tcps = nil + end if (tcps) + if (server) + server.join(5) + if server.alive? + server.kill + server.join + flunk("TCPServer was closed and SSLServer is still alive") unless $! + end end + ensure + tcps.close if (tcps) end end end @@ -180,6 +206,8 @@ ssl.sync_close = true ssl.connect + assert_raise(ArgumentError) { ssl.sysread(-1) } + # syswrite and sysread ITERATIONS.times{|i| str = "x" * 100 + "\n" @@ -193,6 +221,13 @@ assert_equal(str, buf) } + # puts and gets + ITERATIONS.times{ + str = "x" * 100 + "\n" + ssl.puts(str) + assert_equal(str, ssl.gets) + } + # read and write ITERATIONS.times{|i| str = "x" * 100 + "\n" @@ -213,7 +248,7 @@ def test_client_auth vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT start_server(PORT, vflag, true){|server, port| - assert_raises(OpenSSL::SSL::SSLError){ + assert_raise(OpenSSL::SSL::SSLError){ sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) ssl.connect @@ -247,6 +282,82 @@ } end + def test_client_auth_with_server_store + vflag = OpenSSL::SSL::VERIFY_PEER + + localcacert_file = Tempfile.open("cafile") + localcacert_file << @ca_cert.to_pem + localcacert_file.close + localcacert_path = localcacert_file.path + + ssl_store = OpenSSL::X509::Store.new + ssl_store.purpose = OpenSSL::X509::PURPOSE_ANY + ssl_store.add_file(localcacert_path) + + args = {} + args[:ctx_proc] = proc { |server_ctx| + server_ctx.cert = @svr_cert + server_ctx.key = @svr_key + server_ctx.verify_mode = vflag + server_ctx.cert_store = ssl_store + } + + start_server(PORT, vflag, true, args){|server, port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.cert = @cli_cert + ctx.key = @cli_key + sock = TCPSocket.new("127.0.0.1", port) + ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) + ssl.sync_close = true + ssl.connect + ssl.puts("foo") + assert_equal("foo\n", ssl.gets) + ssl.close + localcacert_file.unlink + } + end + + def test_client_crl_with_server_store + vflag = OpenSSL::SSL::VERIFY_PEER + + localcacert_file = Tempfile.open("cafile") + localcacert_file << @ca_cert.to_pem + localcacert_file.close + localcacert_path = localcacert_file.path + + ssl_store = OpenSSL::X509::Store.new + ssl_store.purpose = OpenSSL::X509::PURPOSE_ANY + ssl_store.add_file(localcacert_path) + ssl_store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL|OpenSSL::X509::V_FLAG_CRL_CHECK + + crl = issue_crl([], 1, Time.now, Time.now+1600, [], + @cli_cert, @ca_key, OpenSSL::Digest::SHA1.new) + + ssl_store.add_crl(OpenSSL::X509::CRL.new(crl.to_pem)) + + args = {} + args[:ctx_proc] = proc { |server_ctx| + server_ctx.cert = @svr_cert + server_ctx.key = @svr_key + server_ctx.verify_mode = vflag + server_ctx.cert_store = ssl_store + } + + start_server(PORT, vflag, true, args){|s, p| + ctx = OpenSSL::SSL::SSLContext.new + ctx.cert = @cli_cert + ctx.key = @cli_key + assert_raise(OpenSSL::SSL::SSLError){ + sock = TCPSocket.new("127.0.0.1", p) + ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) + ssl.sync_close = true + ssl.connect + ssl.close + } + localcacert_file.unlink + } + end + def test_starttls start_server(PORT, OpenSSL::SSL::VERIFY_NONE, false){|server, port| sock = TCPSocket.new("127.0.0.1", port) @@ -352,10 +463,10 @@ sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock) ssl.connect - assert_raises(sslerr){ssl.post_connection_check("localhost.localdomain")} - assert_raises(sslerr){ssl.post_connection_check("127.0.0.1")} + assert_raise(sslerr){ssl.post_connection_check("localhost.localdomain")} + assert_raise(sslerr){ssl.post_connection_check("127.0.0.1")} assert(ssl.post_connection_check("localhost")) - assert_raises(sslerr){ssl.post_connection_check("foo.example.com")} + assert_raise(sslerr){ssl.post_connection_check("foo.example.com")} cert = ssl.peer_cert assert(!OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain")) @@ -378,8 +489,8 @@ ssl.connect assert(ssl.post_connection_check("localhost.localdomain")) assert(ssl.post_connection_check("127.0.0.1")) - assert_raises(sslerr){ssl.post_connection_check("localhost")} - assert_raises(sslerr){ssl.post_connection_check("foo.example.com")} + assert_raise(sslerr){ssl.post_connection_check("localhost")} + assert_raise(sslerr){ssl.post_connection_check("foo.example.com")} cert = ssl.peer_cert assert(OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain")) @@ -400,9 +511,9 @@ ssl = OpenSSL::SSL::SSLSocket.new(sock) ssl.connect assert(ssl.post_connection_check("localhost.localdomain")) - assert_raises(sslerr){ssl.post_connection_check("127.0.0.1")} - assert_raises(sslerr){ssl.post_connection_check("localhost")} - assert_raises(sslerr){ssl.post_connection_check("foo.example.com")} + assert_raise(sslerr){ssl.post_connection_check("127.0.0.1")} + assert_raise(sslerr){ssl.post_connection_check("localhost")} + assert_raise(sslerr){ssl.post_connection_check("foo.example.com")} cert = ssl.peer_cert assert(OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain")) assert(!OpenSSL::SSL.verify_certificate_identity(cert, "127.0.0.1")) @@ -494,7 +605,7 @@ ctx.session_add(saved_session) end connections += 1 - + readwrite_loop(ctx, ssl) end @@ -532,6 +643,50 @@ end end end + + def test_tlsext_hostname + return unless OpenSSL::SSL::SSLSocket.instance_methods.include?("hostname") + + ctx_proc = Proc.new do |ctx, ssl| + foo_ctx = ctx.dup + + ctx.servername_cb = Proc.new do |ssl2, hostname| + case hostname + when 'foo.example.com' + foo_ctx + when 'bar.example.com' + nil + else + raise "unknown hostname #{hostname.inspect}" + end + end + end + + server_proc = Proc.new do |ctx, ssl| + readwrite_loop(ctx, ssl) + end + + start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port| + 2.times do |i| + sock = TCPSocket.new("127.0.0.1", port) + ctx = OpenSSL::SSL::SSLContext.new + if defined?(OpenSSL::SSL::OP_NO_TICKET) + # disable RFC4507 support + ctx.options = OpenSSL::SSL::OP_NO_TICKET + end + ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) + ssl.sync_close = true + ssl.hostname = (i & 1 == 0) ? 'foo.example.com' : 'bar.example.com' + ssl.connect + + str = "x" * 100 + "\n" + ssl.puts(str) + assert_equal(str, ssl.gets) + + ssl.close + end + end + end end end Index: test/openssl/max.pem =================================================================== --- test/openssl/max.pem (.../ruby_1_8_7/test/openssl) (revision 0) +++ test/openssl/max.pem (.../ruby_1_8/test/openssl) (revision 27451) @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE4zCCA8ugAwIBAgIDBbhlMA0GCSqGSIb3DQEBBQUAMIGXMQswCQYDVQQGEwJB +VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp +bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMR4wHAYDVQQLDBVhLXNpZ24tUHJl +bWl1bS1FbmMtMDIxHjAcBgNVBAMMFWEtc2lnbi1QcmVtaXVtLUVuYy0wMjAeFw0w +OTA2MjYwOTExMzZaFw0xNDA2MjYwOTExMzZaMGAxCzAJBgNVBAYTAkFUMRcwFQYD +VQQDDA5NYXggTXVzdGVybWFubjETMBEGA1UEBAwKTXVzdGVybWFubjEMMAoGA1UE +KgwDTWF4MRUwEwYDVQQFEww3NTkzNjIxNTE2MTYwgd8wDQYJKoZIhvcNAQEBBQAD +gc0AMIHJAoHBAO+1eEcrMoYJ2S2iybcqUEzIxKQ9yJJL0XRNQSrKo/bDOBibfQ3H +E/TExiivgdXG2p0UjuPO1NEFgxhT5gtdaLthV2Kuokb+vbp3mWoUGz+uHIILT2zJ +TG6Yz6sooi/ppNIagFx3qAdFes8QMAereZQp0zzphK/a21FTLk0GVHpw+DWn7NRn +ynDVY0XgFkHXS4uHSfZDhzMGXVef3+SJLQzsV8R1ThMYQeoizA7tj6hT3YeBID2E +lh86V1Z8XuznUQIDAQABo4IBsDCCAawwEwYDVR0jBAwwCoAIRyFHjpdh4x4wewYI +KwYBBQUHAQEEbzBtMEIGCCsGAQUFBzAChjZodHRwOi8vd3d3LmEtdHJ1c3QuYXQv +Y2VydHMvYS1zaWduLVByZW1pdW0tRW5jLTAyYS5jcnQwJwYIKwYBBQUHMAGGG2h0 +dHA6Ly9vY3NwLmEtdHJ1c3QuYXQvb2NzcDBNBgNVHSAERjBEMEIGBiooABEBDDA4 +MDYGCCsGAQUFBwIBFipodHRwOi8vd3d3LmEtdHJ1c3QuYXQvZG9jcy9jcC9hLXNp +Z24tdG9rZW4wgZoGA1UdHwSBkjCBjzCBjKCBiaCBhoaBg2xkYXA6Ly9sZGFwLmEt +dHJ1c3QuYXQvb3U9YS1zaWduLVByZW1pdW0tRW5jLTAyLG89QS1UcnVzdCxjPUFU +P2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3Q/YmFzZT9vYmplY3RjbGFzcz1laWRD +ZXJ0aWZpY2F0aW9uQXV0aG9yaXR5MBEGA1UdDgQKBAhMueHceqw1zzAOBgNVHQ8B +Af8EBAMCBLAwCQYDVR0TBAIwADANBgkqhkiG9w0BAQUFAAOCAQEASLyAbafKFN5h +0Mkk0QQoUl4Uvl+yy2ECe/QWNmDQpd7UCw1UAKrMvR8p6OcBiTnvbvg1HnbWI3Hy +BaEhGAhb1tziWkbV93z1NQCIt8hmdqE7GEp58ptYSuzwev6rgO/RZIxI9FCQn9kJ +ruGTM8hOIkh3QEy7Mq6utquMOEO0hQSUOvZkJdaSqHAoh2I3SzsxGr3juAa61x+0 +K8kW1ZgIsc0jhhb3NOyso48AqDK6oqwfiC6fp/HzSB5gycLllWrgUnMeae6Axbag +dImyOtaoxhIwZCr1tjTaQmaNK49kpvDGlIuDIQHf8uZgAoyduQfAvwiQ0llu5Ns2 +AOs41se+Gg== +-----END CERTIFICATE----- Property changes on: max.pem ___________________________________________________________________ Added: svn:eol-style + LF Index: test/openssl/test_config.rb =================================================================== --- test/openssl/test_config.rb (.../ruby_1_8_7/test/openssl) (revision 0) +++ test/openssl/test_config.rb (.../ruby_1_8/test/openssl) (revision 27451) @@ -0,0 +1,16 @@ +require 'openssl' +require "test/unit" + +class OpenSSL::TestConfig < Test::Unit::TestCase + def test_freeze + c = OpenSSL::Config.new + c['foo'] = [['key', 'value']] + c.freeze + + # [ruby-core:18377] + # RuntimeError for 1.9, TypeError for 1.8 + assert_raise(TypeError, /frozen/) do + c['foo'] = [['key', 'wrong']] + end + end +end Property changes on: test_config.rb ___________________________________________________________________ Added: svn:eol-style + LF Index: test/openssl/test_x509name.rb =================================================================== --- test/openssl/test_x509name.rb (.../ruby_1_8_7/test/openssl) (revision 27451) +++ test/openssl/test_x509name.rb (.../ruby_1_8/test/openssl) (revision 27451) @@ -6,6 +6,8 @@ if defined?(OpenSSL) +require 'digest/md5' + class OpenSSL::TestX509Name < Test::Unit::TestCase OpenSSL::ASN1::ObjectId.register( "1.2.840.113549.1.9.1", "emailAddress", "emailAddress") @@ -261,6 +263,28 @@ assert_equal(OpenSSL::ASN1::IA5STRING, ary[3][2]) assert_equal(OpenSSL::ASN1::PRINTABLESTRING, ary[4][2]) end + + def name_hash(name) + # OpenSSL 1.0.0 uses SHA1 for canonical encoding (not just a der) of + # X509Name for X509_NAME_hash. + name.respond_to?(:hash_old) ? name.hash_old : name.hash + end + + def calc_hash(d) + (d[0] & 0xff) | (d[1] & 0xff) << 8 | (d[2] & 0xff) << 16 | (d[3] & 0xff) << 24 + end + + def test_hash + dn = "/DC=org/DC=ruby-lang/CN=www.ruby-lang.org" + name = OpenSSL::X509::Name.parse(dn) + d = Digest::MD5.digest(name.to_der) + assert_equal(calc_hash(d), name_hash(name)) + # + dn = "/DC=org/DC=ruby-lang/CN=baz.ruby-lang.org" + name = OpenSSL::X509::Name.parse(dn) + d = Digest::MD5.digest(name.to_der) + assert_equal(calc_hash(d), name_hash(name)) + end end end Index: test/openssl/test_x509crl.rb =================================================================== --- test/openssl/test_x509crl.rb (.../ruby_1_8_7/test/openssl) (revision 27451) +++ test/openssl/test_x509crl.rb (.../ruby_1_8/test/openssl) (revision 27451) @@ -125,13 +125,13 @@ def test_extension cert_exts = [ ["basicConstraints", "CA:TRUE", true], - ["subjectKeyIdentifier", "hash", false], - ["authorityKeyIdentifier", "keyid:always", false], + ["subjectKeyIdentifier", "hash", false], + ["authorityKeyIdentifier", "keyid:always", false], ["subjectAltName", "email:xyzzy@ruby-lang.org", false], ["keyUsage", "cRLSign, keyCertSign", true], ] crl_exts = [ - ["authorityKeyIdentifier", "keyid:always", false], + ["authorityKeyIdentifier", "keyid:always", false], ["issuerAltName", "issuer:copy", false], ] @@ -190,6 +190,30 @@ assert_match((2**100).to_s, crl.extensions[0].value) end + def test_sign_and_verify_wrong_key_type + cert_rsa = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [], + nil, nil, OpenSSL::Digest::SHA1.new) + crl_rsa = issue_crl([], 1, Time.now, Time.now+1600, [], + cert_rsa, @rsa2048, OpenSSL::Digest::SHA1.new) + cert_dsa = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [], + nil, nil, OpenSSL::Digest::DSS1.new) + crl_dsa = issue_crl([], 1, Time.now, Time.now+1600, [], + cert_dsa, @dsa512, OpenSSL::Digest::DSS1.new) + begin + assert_equal(false, crl_rsa.verify(@dsa256)) + rescue OpenSSL::X509::CRLError => e + # OpenSSL 1.0.0 added checks for pkey OID + assert_equal('wrong public key type', e.message) + end + + begin + assert_equal(false, crl_dsa.verify(@rsa1024)) + rescue OpenSSL::X509::CRLError => e + # OpenSSL 1.0.0 added checks for pkey OID + assert_equal('wrong public key type', e.message) + end + end + def test_sign_and_verify cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [], nil, nil, OpenSSL::Digest::SHA1.new) @@ -197,8 +221,6 @@ cert, @rsa2048, OpenSSL::Digest::SHA1.new) assert_equal(false, crl.verify(@rsa1024)) assert_equal(true, crl.verify(@rsa2048)) - assert_equal(false, crl.verify(@dsa256)) - assert_equal(false, crl.verify(@dsa512)) crl.version = 0 assert_equal(false, crl.verify(@rsa2048)) @@ -206,13 +228,26 @@ nil, nil, OpenSSL::Digest::DSS1.new) crl = issue_crl([], 1, Time.now, Time.now+1600, [], cert, @dsa512, OpenSSL::Digest::DSS1.new) - assert_equal(false, crl.verify(@rsa1024)) - assert_equal(false, crl.verify(@rsa2048)) assert_equal(false, crl.verify(@dsa256)) assert_equal(true, crl.verify(@dsa512)) crl.version = 0 assert_equal(false, crl.verify(@dsa512)) end + + def test_create_from_pem + crl = < 0x00907000 def test_ciphers OpenSSL::Cipher.ciphers.each{|name| @@ -90,6 +162,30 @@ } end end + + # JRUBY-4028 + def test_jruby_4028 + key = "0599E113A7EE32A9" + data = "1234567890~5J96LC303C1D22DD~20090930005944~http%3A%2F%2Flocalhost%3A8080%2Flogin%3B0%3B1~http%3A%2F%2Fmix-stage.oracle.com%2F~00" + c1 = OpenSSL::Cipher::Cipher.new("DES-CBC") + c1.padding = 0 + c1.iv = "0" * 8 + c1.encrypt + c1.key = key + e = c1.update data + e << c1.final + + c2 = OpenSSL::Cipher::Cipher.new("DES-CBC") + c2.padding = 0 + c2.iv = "0" * 8 + c2.decrypt + c2.key = key + d = c2.update e + d << c2.final + + assert_equal "\342\320B.\300&X\310\344\253\025\215\017*\22015\344\024D\342\213\361\336\311\271\326\016\243\214\026\2545\002\237,\017s\202\316&Ew\323\221H\376\200\304\201\365\332Im\240\361\037\246\3536\001A2\341\324o0\350\364%=\325\330\240\324u\225\304h\277\272\361f\024\324\352\336\353N\002/]C\370!\003)\212oa\225\207\333\340\245\207\024\351\037\327[\212\001{\216\f\315\345\372\v\226\r\233?\002\vJK", e + assert_equal data, d + end end end Index: test/openssl/test_x509req.rb =================================================================== --- test/openssl/test_x509req.rb (.../ruby_1_8_7/test/openssl) (revision 27451) +++ test/openssl/test_x509req.rb (.../ruby_1_8/test/openssl) (revision 27451) @@ -103,38 +103,89 @@ assert_equal(exts, get_ext_req(attrs[1].value)) end + def test_sign_and_verify_wrong_key_type + req_rsa = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new) + req_dsa = issue_csr(0, @dn, @dsa512, OpenSSL::Digest::DSS1.new) + begin + assert_equal(false, req_rsa.verify(@dsa256)) + rescue OpenSSL::X509::RequestError => e + # OpenSSL 1.0.0 added checks for pkey OID + assert_equal('wrong public key type', e.message) + end + + begin + assert_equal(false, req_dsa.verify(@rsa1024)) + rescue OpenSSL::X509::RequestError => e + # OpenSSL 1.0.0 added checks for pkey OID + assert_equal('wrong public key type', e.message) + end + end + def test_sign_and_verify req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new) assert_equal(true, req.verify(@rsa1024)) assert_equal(false, req.verify(@rsa2048)) - assert_equal(false, req.verify(@dsa256)) - assert_equal(false, req.verify(@dsa512)) req.version = 1 assert_equal(false, req.verify(@rsa1024)) req = issue_csr(0, @dn, @rsa2048, OpenSSL::Digest::MD5.new) assert_equal(false, req.verify(@rsa1024)) assert_equal(true, req.verify(@rsa2048)) - assert_equal(false, req.verify(@dsa256)) - assert_equal(false, req.verify(@dsa512)) req.subject = OpenSSL::X509::Name.parse("/C=JP/CN=FooBar") assert_equal(false, req.verify(@rsa2048)) req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest::DSS1.new) - assert_equal(false, req.verify(@rsa1024)) - assert_equal(false, req.verify(@rsa2048)) assert_equal(false, req.verify(@dsa256)) assert_equal(true, req.verify(@dsa512)) req.public_key = @rsa1024.public_key assert_equal(false, req.verify(@dsa512)) + end - assert_raise(OpenSSL::X509::RequestError){ - issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::DSS1.new) } - assert_raise(OpenSSL::X509::RequestError){ - issue_csr(0, @dn, @dsa512, OpenSSL::Digest::SHA1.new) } - assert_raise(OpenSSL::X509::RequestError){ - issue_csr(0, @dn, @dsa512, OpenSSL::Digest::MD5.new) } + def test_dsig_algorithm_mismatch + assert_raise(OpenSSL::X509::RequestError) do + issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::DSS1.new) + end + assert_raise(OpenSSL::X509::RequestError) do + issue_csr(0, @dn, @dsa512, OpenSSL::Digest::MD5.new) + end end + + def test_create_from_pem + req = <