* lib/net/http.rb (Net::HTTP#connect): use

OpenSSL::SSL::SSLContext.build instead of SSLContext.new (default
  verify mode is now OpenSSL::SSL::VERIFY_PEER).

* lib/net/https.rb: SSL parameters are defined by attr_accessor.

* test/net/http/test_https.rb: add test for HTTPS features.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14371 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
gotoyuzo 2007-12-20 16:21:22 +00:00
Родитель d86caf3188
Коммит c6920177f3
5 изменённых файлов: 139 добавлений и 51 удалений

Просмотреть файл

@ -1,3 +1,13 @@
Fri Dec 21 01:20:56 2007 GOTOU Yuuzou <gotoyuzo@notwork.org>
* lib/net/http.rb (Net::HTTP#connect): use
OpenSSL::SSL::SSLContext.build instead of SSLContext.new (default
verify mode is now OpenSSL::SSL::VERIFY_PEER).
* lib/net/https.rb: SSL parameters are defined by attr_accessor.
* test/net/http/test_https.rb: add test for HTTPS features.
Fri Dec 21 01:11:37 2007 GOTOU Yuuzou <gotoyuzo@notwork.org>
* io.c (select_internal): should return original value.

Просмотреть файл

@ -575,10 +575,13 @@ module Net #:nodoc:
s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) }
D "opened"
if use_ssl?
unless @ssl_context.verify_mode
warn "warning: peer certificate won't be verified in this SSL session"
@ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
ssl_parameters = Hash.new
SSL_ATTRIBUTES.each do |name|
if value = instance_variable_get("@#{name}")
ssl_parameters[name] = value
end
end
@ssl_context = OpenSSL::SSL::SSLContext.build(ssl_parameters)
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
s.sync_close = true
end

Просмотреть файл

@ -102,70 +102,35 @@ require 'net/http'
require 'openssl'
module Net
class HTTP
remove_method :use_ssl?
def use_ssl?
@use_ssl
end
alias use_ssl use_ssl? # for backward compatibility
# Turn on/off SSL.
# This flag must be set before starting session.
# If you change use_ssl value after session started,
# a Net::HTTP object raises IOError.
def use_ssl=(flag)
flag = (flag ? true : false)
raise IOError, "use_ssl value changed, but session already started" \
if started? and @use_ssl != flag
if flag and not @ssl_context
@ssl_context = OpenSSL::SSL::SSLContext.new
if started? and @use_ssl != flag
raise IOError, "use_ssl value changed, but session already started"
end
@use_ssl = flag
end
def self.ssl_context_accessor(name)
module_eval(<<-End, __FILE__, __LINE__ + 1)
def #{name}
return nil unless @ssl_context
@ssl_context.#{name}
end
def #{name}=(val)
@ssl_context ||= OpenSSL::SSL::SSLContext.new
@ssl_context.#{name} = val
end
End
end
ssl_context_accessor :key
ssl_context_accessor :cert
ssl_context_accessor :ca_file
ssl_context_accessor :ca_path
ssl_context_accessor :verify_mode
ssl_context_accessor :verify_callback
ssl_context_accessor :verify_depth
ssl_context_accessor :cert_store
def ssl_timeout
return nil unless @ssl_context
@ssl_context.timeout
end
def ssl_timeout=(sec)
raise ArgumentError, 'Net::HTTP#ssl_timeout= called but use_ssl=false' \
unless use_ssl?
@ssl_context ||= OpenSSL::SSL::SSLContext.new
@ssl_context.timeout = sec
end
alias timeout= ssl_timeout= # for backward compatibility
SSL_ATTRIBUTES = %w(
ssl_version key cert ca_file ca_path cert_store ciphers
verify_mode verify_callback verify_depth ssl_timeout
)
attr_accessor *SSL_ATTRIBUTES
def peer_cert
return nil if not use_ssl? or not @socket
if not use_ssl? or not @socket
return nil
end
@socket.io.peer_cert
end
end
end

Просмотреть файл

@ -0,0 +1,97 @@
require "test/unit"
begin
require 'net/https'
rescue LoadError
# should skip this test
end
require 'stringio'
require File.expand_path("utils", File.dirname(__FILE__))
require File.expand_path("../../openssl/utils", File.dirname(__FILE__))
class TestNetHTTPS < Test::Unit::TestCase
include TestNetHTTPUtils
subject = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
exts = [
["keyUsage", "keyEncipherment,digitalSignature", true],
]
key = OpenSSL::TestUtils::TEST_KEY_RSA1024
cert = OpenSSL::TestUtils.issue_cert(
subject, key, 1, Time.now, Time.now + 3600, exts,
nil, nil, OpenSSL::Digest::SHA1.new
)
CONFIG = {
'host' => '127.0.0.1',
'port' => 10081,
'proxy_host' => nil,
'proxy_port' => nil,
'ssl_enable' => true,
'ssl_certificate' => cert,
'ssl_private_key' => key,
}
def test_get
http = Net::HTTP.new("localhost", config("port"))
http.use_ssl = true
http.verify_callback = Proc.new do |preverify_ok, store_ctx|
store_ctx.current_cert.to_der == config('ssl_certificate').to_der
end
http.request_get("/") {|res|
assert_equal($test_net_http_data, res.body)
}
end
def test_post
http = Net::HTTP.new("localhost", config("port"))
http.use_ssl = true
http.verify_callback = Proc.new do |preverify_ok, store_ctx|
store_ctx.current_cert.to_der == config('ssl_certificate').to_der
end
data = config('ssl_private_key').to_der
http.request_post("/", data) {|res|
assert_equal(data, res.body)
}
end
if ENV["RUBY_OPENSSL_TEST_ALL"]
def test_verify
http = Net::HTTP.new("ssl.netlab.jp", 443)
http.use_ssl = true
assert(
http.request_head("/"){|res| },
"The system may not have default CA certificate store."
)
end
end
def test_verify_none
http = Net::HTTP.new("localhost", config("port"))
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.request_get("/") {|res|
assert_equal($test_net_http_data, res.body)
}
end
def test_certificate_verify_failure
http = Net::HTTP.new("localhost", config("port"))
http.use_ssl = true
ex = assert_raise(OpenSSL::SSL::SSLError){
http.request_get("/") {|res| }
}
assert_match(/certificate verify failed/, ex.message)
end
def test_identity_verify_failure
http = Net::HTTP.new("127.0.0.1", config("port"))
http.use_ssl = true
http.verify_callback = Proc.new do |preverify_ok, store_ctx|
store_ctx.current_cert.to_der == config('ssl_certificate').to_der
end
ex = assert_raise(OpenSSL::SSL::SSLError){
http.request_get("/") {|res| }
}
assert_match(/hostname was not match/, ex.message)
end
end if defined?(OpenSSL)

Просмотреть файл

@ -1,4 +1,9 @@
require 'webrick'
begin
require "webrick/https"
rescue LoadError
# SSL features cannot be tested
end
require 'webrick/httpservlet/abstract'
module TestNetHTTPUtils
@ -35,14 +40,22 @@ module TestNetHTTPUtils
end
def spawn_server
@server = WEBrick::HTTPServer.new(
server_config = {
:BindAddress => config('host'),
:Port => config('port'),
:Logger => WEBrick::Log.new(NullWriter.new),
:AccessLog => [],
:ShutdownSocketWithoutClose => true,
:ServerType => Thread
)
:ServerType => Thread,
}
if defined?(OpenSSL) and config('ssl_enable')
server_config.update({
:SSLEnable => true,
:SSLCertificate => config('ssl_certificate'),
:SSLPrivateKey => config('ssl_private_key'),
})
end
@server = WEBrick::HTTPServer.new(server_config)
@server.mount('/', Servlet)
@server.start
n_try_max = 5