In message <20041217235948.311035a2.sheepman / tcn.zaq.ne.jp>,
 `sheepman <sheepman / tcn.zaq.ne.jp>' wrote:
> net/https.rb と net/http.rb で RFC2818 の 3.1 に定められた
> 「サーバーの証明書に記載された身元のチェック」をしていないのは意図されたことでしょうか。

ええと、チェックしないことを意図しているわけではありませんが、
実装されていないのでチェックされません。

> クライアントが信頼している CA に署名された、証明書をもつサーバーが DNS spoofing などと
> 連係して偽の名前を名乗ることが出来てしまいます。

証明書を検証しなければこのチェックには意味がありませんが、デ
フォルトでは行なっていませんから、ホスト名が一致しないときに
必ず例外を上げるというのは適切でない気がします。

ひとまず、sheepmanさんのパッチを参考にユーザ側で対処するコー
ドを書いてみました。これくらいは組み込まれていた方がいいので
しょうね。

require "net/https"
require 'uri'

def post_connection_check(cert, hostname)
  subject = cert.subject
  subject.to_a.each{|oid, value|
    if oid == "CN" && value == hostname
      return true
    end
  }
  cert.extensions.each{|ext|
    if ext.oid == "subjectAltName"
      general_names = ext.value.split(/,\s+/)
      general_names.each{|name|
        if /(:?DNS|IP Address):(.*)/ =~ name
          reg = Regexp.escape($1)
          reg = reg.gsub(%r!\\\*!, '[^.]+')
          reg = Regexp.new('\A' + reg + '\z')
          if reg.match(hostname)
            return true
          end
        end
      }
    end
  }
  return false
end

uri = URI.parse(ARGV[0] || 'https://localhost/')
http = Net::HTTP.new(uri.host, uri.port)
if uri.scheme == "https"  # enable SSL/TLS
  http.use_ssl = true
end
http.start{
  if (http.verify_mode & OpenSSL::SSL::VERIFY_PEER) != 0
    unless post_connection_check(http.peer_cert, uri.host)
      raise "hostname not match"
    end
  end
  http.request_get(uri.path){|res|
    p res.body.size
  }
}

-- 
ごとうゆうぞう