From: Shugo Maeda Date: 2007-12-21T16:56:32+09:00 Subject: [ruby-dev:32665] Net::POP3#enable_sslの仕様変更 This is a multi-part message in MIME format. --------------040409030808060704000005 Content-Type: text/plain; charset=ISO-2022-JP Content-Transfer-Encoding: 7bit 前田です。 Net::POP3#enable_ssl(とNet::POP3.enable_ssl)の仕様変更を提案します。 変更点は以下の2点です。 (1) デフォルトのverify_modeをVERIFY_PEERにする (2) 第1引数がハッシュだったらSSLContext.buildにそのまま渡す (それ以外の場合は、(1)以外は以前と同じ挙動) ただし、:portはポート番号として扱い、buildには渡さない。 パッチを添付しますので、検討をお願いします。 というか、ゆうぞうさんの賛同が得られればcommitしてしまうかも しれませんが許してください。 -- 前田 修吾 ほんとに1.9.1でライブラリの仕様もフリーズするんですかねえ…。 --------------040409030808060704000005 Content-Type: text/x-patch; name="pop3s.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pop3s.diff" Index: lib/net/pop.rb =================================================================== --- lib/net/pop.rb (revision 14409) +++ lib/net/pop.rb (working copy) @@ -25,7 +25,7 @@ require 'timeout' begin - require "openssl" + require "openssl/ssl" rescue LoadError end @@ -322,38 +322,53 @@ # SSL # - @use_ssl = false - @verify = nil - @certs = nil + @ssl_params = nil # Enable SSL for all new instances. # +verify+ is the type of verification to do on the Server Cert; Defaults - # to OpenSSL::SSL::VERIFY_NONE. + # to OpenSSL::SSL::VERIFY_PEER. # +certs+ is a file or directory holding CA certs to use to verify the # server cert; Defaults to nil. - def POP3.enable_ssl(verify = OpenSSL::SSL::VERIFY_NONE, certs = nil) - @use_ssl = true - @verify = verify - @certs = certs + def POP3.enable_ssl(*args) + @ssl_params = create_ssl_params(*args) end + def POP3.create_ssl_params(verify_or_params = {}, certs = nil) + begin + params = verify_or_params.to_hash + rescue NoMethodError + params = {} + params[:verify_mode] = verify_or_params + if certs + if File.file?(certs) + params[:ca_file] = certs + elsif File.directory?(certs) + params[:ca_path] = certs + end + end + end + return params + end + # Disable SSL for all new instances. def POP3.disable_ssl - @use_ssl = nil - @verify = nil - @certs = nil + @ssl_params = nil end + def POP3.ssl_params + return @ssl_params + end + def POP3.use_ssl? - @use_ssl + return !@ssl_params.nil? end def POP3.verify - @verify + return @ssl_params[:verify_mode] end def POP3.certs - @certs + return @ssl_params[:ca_file] || @ssl_params[:ca_path] end # @@ -394,11 +409,9 @@ # This method does *not* open the TCP connection. def initialize(addr, port = nil, isapop = false) @address = addr - @use_ssl = POP3.use_ssl? - @port = port || (POP3.use_ssl? ? POP3.default_pop3s_port : POP3.default_pop3_port) + @ssl_params = POP3.ssl_params + @port = port @apop = isapop - @certs = POP3.certs - @verify = POP3.verify @command = nil @socket = nil @@ -419,28 +432,28 @@ # does this instance use SSL? def use_ssl? - @use_ssl + return !@ssl_params.nil? end # Enables SSL for this instance. Must be called before the connection is # established to have any effect. # +verify+ is the type of verification to do on the Server Cert; Defaults - # to OpenSSL::SSL::VERIFY_NONE. + # to OpenSSL::SSL::VERIFY_PEER. # +certs+ is a file or directory holding CA certs to use to verify the # server cert; Defaults to nil. # +port+ is port to establish the SSL connection on; Defaults to 995. - def enable_ssl(verify = OpenSSL::SSL::VERIFY_NONE, certs = nil, - port = POP3.default_pop3s_port) - @use_ssl = true - @verify = verify - @certs = certs - @port = port + def enable_ssl(verify_or_params = {}, certs = nil, port = nil) + begin + @ssl_params = verify_or_params.to_hash.dup + @port = @ssl_params.delete(:port) || @port + rescue NoMethodError + @ssl_params = POP3.create_ssl_params(verify_or_params, certs) + @port = port || @port + end end def disable_ssl - @use_ssl = false - @verify = nil - @certs = nil + @ssl_params = nil end # Provide human-readable stringification of class state. @@ -469,7 +482,9 @@ attr_reader :address # The port number to connect to. - attr_reader :port + def port + return @port || (use_ssl? ? POP3.default_pop3s_port : POP3.default_pop3_port) + end # Seconds to wait until a connection is opened. # If the POP3 object cannot open a connection within this time, @@ -516,20 +531,10 @@ end def do_start(account, password) - s = timeout(@open_timeout) { TCPSocket.open(@address, @port) } + s = timeout(@open_timeout) { TCPSocket.open(@address, port) } if use_ssl? raise 'openssl library not installed' unless defined?(OpenSSL) - context = OpenSSL::SSL::SSLContext.new - context.verify_mode = @verify - if @certs - if File.file?(@certs) - context.ca_file = @certs - elsif File.directory?(@certs) - context.ca_path = @certs - else - raise ArgumentError, "certs path is not file/directory: #{@certs}" - end - end + context = OpenSSL::SSL::SSLContext.build(@ssl_params) s = OpenSSL::SSL::SSLSocket.new(s, context) s.sync_close = true s.connect --------------040409030808060704000005--