[前][次][番号順一覧][スレッド一覧]

ruby-changes:20362

From: naruse <ko1@a...>
Date: Tue, 5 Jul 2011 14:06:39 +0900 (JST)
Subject: [ruby-changes:20362] naruse:r32410 (trunk): * lib/webrick/httpauth/digestauth.rb (_authenticate):

naruse	2011-07-05 14:06:05 +0900 (Tue, 05 Jul 2011)

  New Revision: 32410

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=32410

  Log:
    * lib/webrick/httpauth/digestauth.rb (_authenticate):
      Literal texts in HTTP ABNF is case-insensitive (RFC2616 2.1),
      and a ample implementation in RFC2617 also ignores the case
      of algorithms. So now this ignores those cases.
      [ruby-dev:43965] [Feature #4936]
    
    * lib/webrick/httpauth/digestauth.rb (initialize):
      Because of above, opera_hack is useless and removed.

  Modified files:
    trunk/ChangeLog
    trunk/lib/webrick/httpauth/digestauth.rb
    trunk/test/webrick/test_httpauth.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 32409)
+++ ChangeLog	(revision 32410)
@@ -1,3 +1,14 @@
+Tue Jul  5 14:05:43 2011  NARUSE, Yui  <naruse@r...>
+
+	* lib/webrick/httpauth/digestauth.rb (_authenticate):
+	  Literal texts in HTTP ABNF is case-insensitive (RFC2616 2.1),
+	  and a ample implementation in RFC2617 also ignores the case
+	  of algorithms. So now this ignores those cases.
+	  [ruby-dev:43965] [Feature #4936]
+
+	* lib/webrick/httpauth/digestauth.rb (initialize):
+	  Because of above, opera_hack is useless and removed.
+
 Tue Jul  5 01:30:01 2011  Yusuke Endoh  <mame@t...>
 
 	* thread_pthread.c (native_sleep): cut the waiting time up to
Index: lib/webrick/httpauth/digestauth.rb
===================================================================
--- lib/webrick/httpauth/digestauth.rb	(revision 32409)
+++ lib/webrick/httpauth/digestauth.rb	(revision 32410)
@@ -83,7 +83,6 @@
         @nonce_expire_period    = @config[:NonceExpirePeriod]
         @nonce_expire_delta     = @config[:NonceExpireDelta]
         @internet_explorer_hack = @config[:InternetExplorerHack]
-        @opera_hack             = @config[:OperaHack]
 
         case @algorithm
         when 'MD5','MD5-sess'
@@ -175,8 +174,7 @@
         end
 
         auth_req['algorithm'] ||= 'MD5'
-        if auth_req['algorithm'] != @algorithm &&
-           (@opera_hack && auth_req['algorithm'] != @algorithm.upcase)
+        if auth_req['algorithm'].upcase != @algorithm.upcase
           error('%s: algorithm unmatch. "%s" for "%s"',
                 auth_req['username'], auth_req['algorithm'], @algorithm)
           return false
@@ -212,8 +210,7 @@
           nonce_is_invalid = true
         end
 
-        if /-sess$/ =~ auth_req['algorithm'] ||
-           (@opera_hack && /-SESS$/ =~ auth_req['algorithm'])
+        if /-sess$/i =~ auth_req['algorithm']
           ha1 = hexdigest(password, auth_req['nonce'], auth_req['cnonce'])
         else
           ha1 = password
Index: test/webrick/test_httpauth.rb
===================================================================
--- test/webrick/test_httpauth.rb	(revision 32409)
+++ test/webrick/test_httpauth.rb	(revision 32410)
@@ -79,4 +79,89 @@
     }
     tmpfile.close(true)
   end
+
+  DIGESTRES_ = /
+    ([a-zA-z\-]+)
+      [\s\t]*(?:\r\n[\s\t]*)*
+      =
+      [\s\t]*(?:\r\n[\s\t]*)*
+      (?:
+       "((?:[^"]+|\\[\x00-\x7F])*)" |
+       ([!\#$%&'*+\-.0-9A-Z^_`a-z|~]+)
+      )/x
+
+  def test_digest_auth
+    TestWEBrick.start_httpserver{|server, addr, port, log|
+      realm = "WEBrick's realm"
+      path = "/digest_auth"
+
+      tmpfile = Tempfile.new("test_webrick_auth")
+      tmpfile.close
+      tmp_pass = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
+      tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
+      tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
+      tmp_pass.flush
+
+      htdigest = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
+      users = []
+      htdigest.each{|user, pass| users << user }
+      assert_equal(2, users.size, log.call)
+      assert(users.member?("webrick"), log.call)
+      assert(users.member?("foo"), log.call)
+
+      auth = WEBrick::HTTPAuth::DigestAuth.new(
+        :Realm => realm, :UserDB => htdigest,
+        :Algorithm => 'MD5',
+        :Logger => server.logger
+      )
+      server.mount_proc(path){|req, res|
+        auth.authenticate(req, res)
+        res.body = "hoge"
+      }
+
+      Net::HTTP.start(addr, port) do |http|
+        g = Net::HTTP::Get.new(path)
+        params = {}
+        http.request(g) do |res|
+          assert_equal('401', res.code, log.call)
+          res["www-authenticate"].scan(DIGESTRES_) do |key, quoted, token|
+            params[key.downcase] = token || quoted.delete('\\')
+          end
+           params['uri'] = "http://#{addr}:#{port}#{path}"
+        end
+
+        g['Authorization'] = credentials_for_request('webrick', "supersecretpassword", params)
+        http.request(g){|res| assert_equal("hoge", res.body, log.call)}
+
+        params['algorithm'].downcase! #4936
+        g['Authorization'] = credentials_for_request('webrick', "supersecretpassword", params)
+        http.request(g){|res| assert_equal("hoge", res.body, log.call)}
+
+        g['Authorization'] = credentials_for_request('webrick', "not super", params)
+        http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
+      end
+    }
+  end
+
+  private
+  def credentials_for_request(user, password, params)
+    cnonce = "hoge"
+    nonce_count = 1
+    ha1 = "#{user}:#{params['realm']}:#{password}"
+    ha2 = "GET:#{params['uri']}"
+    request_digest =
+      "#{Digest::MD5.hexdigest(ha1)}:" \
+      "#{params['nonce']}:#{'%08x' % nonce_count}:#{cnonce}:#{params['qop']}:" \
+      "#{Digest::MD5.hexdigest(ha2)}"
+    p header = "Digest username=\"#{user}\"" \
+      ", realm=\"#{params['realm']}\"" \
+      ", nonce=\"#{params['nonce']}\"" \
+      ", uri=\"#{params['uri']}\"" \
+      ", qop=#{params['qop']}" \
+      ", nc=#{'%08x' % nonce_count}" \
+      ", cnonce=\"#{cnonce}\"" \
+      ", response=\"#{Digest::MD5.hexdigest(request_digest)}\"" \
+      ", opaque=\"#{params['opaque']}\"" \
+      ", algorithm=#{params['algorithm']}"
+  end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]