Welcome to the "trac"-ing site of http-access2!
[soap4r] [httpclient] [openpgp4u] [pkcs1] [logger] [csv] [vtr]

Changeset 259

Show
Ignore:
Timestamp:
01/08/09 21:49:04 (1 year ago)
Author:
nahi
Message:
  • Security fix introduced at 2.1.3.
    • get_content/post_content of httpclient/2.1.3 may send secure cookies
      for a https site to non-secure (non-https) site when the https site
      redirects the request to a non-https site. httpclient/2.1.3 caches
      request object and reuses it for redirection. It should not be cached
      and recreated for each time as httpclient <= 2.1.2 and http-access2.
    • I realized this bug when I was reading open-uri story on
      [ruby-core:21205]. Ruby users should use open-uri rather than using
      net/http directly wherever possible.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/README.txt

    r256 r259  
    11httpclient - HTTP accessing library. 
    2 Copyright (C) 2000-2008  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
     2Copyright (C) 2000-2009  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
    33 
    44'httpclient' gives something like the functionality of libwww-perl (LWP) in 
     
    6969 
    7070 
     71== Download 
     72 
     73* Stable: http://dev.ctor.org/download/httpclient-2.1.3.1.tar.gz (tar + gzip) 
     74* Stable: http://dev.ctor.org/download/httpclient-2.1.3.1.zip (ZIP)  
     75 
     76* Older versions: http://dev.ctor.org/download/archive/  
     77 
     78* Gem repository for stable version 
     79  * (at default remove source at rubyforge.org)  
     80* Gem repository for development version 
     81  * http://dev.ctor.org/download/  
     82 
     83* svn: http://dev.ctor.org/svn/http-access2/trunk/  
     84 
     85=== Gem 
     86 
     87You can install httpclient with rubygems. 
     88 
     89  % gem install httpclient --source http://dev.ctor.org/download/ 
     90 
     91 
    7192== Bug report or Feature request 
    7293 
     
    81102 
    82103== Changes 
     104 
     105  Jan 8, 2009 - version 2.1.3.1 
     106 
     107    * Security fix introduced at 2.1.3. 
     108      * get_content/post_content of httpclient/2.1.3 may send secure cookies 
     109        for a https site to non-secure (non-https) site when the https site 
     110        redirects the request to a non-https site.  httpclient/2.1.3 caches 
     111        request object and reuses it for redirection.  It should not be cached 
     112        and recreated for each time as httpclient <= 2.1.2 and http-access2. 
     113      * I realized this bug when I was reading open-uri story on 
     114        [ruby-core:21205].  Ruby users should use open-uri rather than using 
     115        net/http directly wherever possible. 
    83116 
    84117  Dec 29, 2008 - version 2.1.3 
  • trunk/httpclient.gemspec

    r187 r259  
    22SPEC = Gem::Specification.new do |s| 
    33  s.name = "httpclient" 
    4   s.version = "2.1.2
    5   s.date = "2007-09-22
     4  s.version = "2.1.3.1
     5  s.date = "2009-01-08
    66  s.author = "NAKAMURA, Hiroshi" 
    77  s.email = "nahi@ruby-lang.org" 
  • trunk/lib/httpclient.rb

    r256 r259  
    11# HTTPClient - HTTP client library. 
    2 # Copyright (C) 2000-2008  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
     2# Copyright (C) 2000-2009  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
    33# 
    44# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can 
     
    200200# 
    201201class HTTPClient 
    202   VERSION = '2.1.3
     202  VERSION = '2.1.3.1
    203203  RUBY_VERSION_STRING = "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" 
    204204  /: (\S+) (\S+)/ =~ %q$Id$ 
     
    512512  # follow HTTP redirect by yourself if you need. 
    513513  def get_content(uri, query = nil, extheader = {}, &block) 
    514     uri = urify(uri) 
    515     req = create_request('GET', uri, query, nil, extheader) 
    516     follow_redirect(req, &block).content 
     514    follow_redirect(:get, uri, query, nil, extheader, &block).content 
    517515  end 
    518516 
     
    540538  # use post method. 
    541539  def post_content(uri, body = nil, extheader = {}, &block) 
    542     uri = urify(uri) 
    543     req = create_request('POST', uri, nil, body, extheader) 
    544     follow_redirect(req, &block).content 
     540    follow_redirect(:post, uri, nil, body, extheader, &block).content 
    545541  end 
    546542 
     
    552548  def strict_redirect_uri_callback(uri, res) 
    553549    newuri = URI.parse(res.header['location'][0]) 
     550    if https?(uri) && !https?(newuri) 
     551      raise BadResponseError.new("redirecting to non-https resource") 
     552    end 
    554553    unless newuri.is_a?(URI::HTTP) 
    555554      raise BadResponseError.new("unexpected location: #{newuri}", res) 
     
    566565  def default_redirect_uri_callback(uri, res) 
    567566    newuri = URI.parse(res.header['location'][0]) 
     567    if https?(uri) && !https?(newuri) 
     568      raise BadResponseError.new("redirecting to non-https resource") 
     569    end 
    568570    unless newuri.is_a?(URI::HTTP) 
    569571      newuri = uri + newuri 
     
    653655    uri = urify(uri) 
    654656    proxy = no_proxy?(uri) ? nil : @proxy 
    655     req = create_request(method.to_s.upcase, uri, query, body, extheader) 
     657    req = create_request(method, uri, query, body, extheader) 
    656658    if block 
    657659      filtered_block = proc { |res, str| 
     
    723725    uri = urify(uri) 
    724726    proxy = no_proxy?(uri) ? nil : @proxy 
    725     req = create_request(method.to_s.upcase, uri, query, body, extheader) 
     727    req = create_request(method, uri, query, body, extheader) 
    726728    do_request_async(req, proxy) 
    727729  end 
     
    803805  end 
    804806 
    805   def follow_redirect(req, &block) 
    806     retry_number = 0 
     807  def follow_redirect(method, uri, query, body, extheader, &block) 
     808    uri = urify(uri) 
    807809    if block 
    808810      filtered_block = proc { |r, str| 
     
    810812      } 
    811813    end 
     814    if HTTP::Message.file?(body) 
     815      pos = body.pos rescue nil 
     816    end 
     817    retry_number = 0 
    812818    while retry_number < @follow_redirect_count 
     819      body.pos = pos if pos 
     820      req = create_request(method, uri, query, body, extheader) 
    813821      proxy = no_proxy?(req.header.request_uri) ? nil : @proxy 
    814822      res = do_request(req, proxy, &filtered_block) 
     
    817825      elsif HTTP::Status.redirect?(res.status) 
    818826        uri = urify(@redirect_uri_callback.call(req.header.request_uri, res)) 
    819         req.header.request_uri = uri 
    820827        retry_number += 1 
    821828      else 
     
    835842 
    836843  def create_request(method, uri, query, body, extheader) 
     844    method = method.to_s.upcase 
    837845    if extheader.is_a?(Hash) 
    838846      extheader = extheader.to_a 
     
    914922  end 
    915923 
     924  def https?(uri) 
     925    uri.scheme.downcase == 'https' 
     926  end 
     927 
    916928  # !! CAUTION !! 
    917929  #   Method 'do_get*' runs under MT conditon. Be careful to change. 
  • trunk/lib/httpclient/auth.rb

    r254 r259  
    11# HTTPClient - HTTP client library. 
    2 # Copyright (C) 2000-2008  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
     2# Copyright (C) 2000-2009  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
    33# 
    44# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can 
  • trunk/lib/httpclient/connection.rb

    r252 r259  
    11# HTTPClient - HTTP client library. 
    2 # Copyright (C) 2000-2008  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
     2# Copyright (C) 2000-2009  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
    33# 
    44# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can 
  • trunk/lib/httpclient/http.rb

    r256 r259  
    11# HTTPClient - HTTP client library. 
    2 # Copyright (C) 2000-2008  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
     2# Copyright (C) 2000-2009  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
    33# 
    44# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can 
  • trunk/lib/httpclient/session.rb

    r256 r259  
    11# HTTPClient - HTTP client library. 
    2 # Copyright (C) 2000-2008  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
     2# Copyright (C) 2000-2009  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
    33# 
    44# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can 
  • trunk/lib/httpclient/ssl_config.rb

    r254 r259  
    11# HTTPClient - HTTP client library. 
    2 # Copyright (C) 2000-2008  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
     2# Copyright (C) 2000-2009  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
    33# 
    44# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can 
  • trunk/lib/httpclient/timeout.rb

    r254 r259  
    11# HTTPClient - HTTP client library. 
    2 # Copyright (C) 2000-2008  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
     2# Copyright (C) 2000-2009  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
    33# 
    44# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can 
  • trunk/lib/httpclient/util.rb

    r254 r259  
    11# HTTPClient - HTTP client library. 
    2 # Copyright (C) 2000-2008  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
     2# Copyright (C) 2000-2009  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>. 
    33# 
    44# This program is copyrighted free software by NAKAMURA, Hiroshi.  You can 
  • trunk/test/test_httpclient.rb

    r253 r259  
    305305    @client.test_loopback_http_response << "HTTP/1.0 200 OK\nXXXXX\ncontent-length: 100\n\nmessage body 1" 
    306306    assert_equal('message body 1', @client.get_content('http://somewhere')) 
     307  end 
     308 
     309  def test_redirect_non_https 
     310    url = @url + 'redirect1' 
     311    https_url = URI.parse(url) 
     312    https_url.scheme = 'https' 
     313    # 
     314    redirect_to_http = "HTTP/1.0 302 OK\nLocation: #{url}\n\n" 
     315    redirect_to_https = "HTTP/1.0 302 OK\nLocation: #{https_url}\n\n" 
     316    # 
     317    # https -> http is denied 
     318    @client.test_loopback_http_response << redirect_to_http 
     319    assert_raises(HTTPClient::BadResponseError) do 
     320      @client.get_content(https_url) 
     321    end 
     322    # 
     323    # http -> http is OK 
     324    @client.reset_all 
     325    @client.test_loopback_http_response << redirect_to_http 
     326    assert_equal('hello', @client.get_content(url)) 
     327    # 
     328    # http -> https is OK 
     329    @client.reset_all 
     330    @client.test_loopback_http_response << redirect_to_https 
     331    assert_raises(OpenSSL::SSL::SSLError) do 
     332      # trying to normal endpoint with SSL -> SSL negotiation failure 
     333      @client.get_content(url) 
     334    end 
     335    # 
     336    # https -> https is OK 
     337    @client.reset_all 
     338    @client.test_loopback_http_response << redirect_to_https 
     339    assert_raises(OpenSSL::SSL::SSLError) do 
     340      # trying to normal endpoint with SSL -> SSL negotiation failure 
     341      @client.get_content(https_url) 
     342    end 
    307343  end 
    308344