зеркало из https://github.com/github/ruby.git
* 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:
Родитель
d86caf3188
Коммит
c6920177f3
10
ChangeLog
10
ChangeLog
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче