From a1c9ee2b0b4bf0f0912e0ba8b566ba28aa2cf2f1 Mon Sep 17 00:00:00 2001 From: naruse Date: Wed, 28 Mar 2018 09:26:13 +0000 Subject: webrick: add test for Digest auth-int No changes to the actual code, this is a new test for a feature for which no tests existed. I don't understand the Digest authentication code well at all, but this is necessary for the subsequent change. * test/webrick/test_httpauth.rb (test_digest_auth_int): new test (credentials_for_request): support bodies with POST git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_5@62983 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/webrick/test_httpauth.rb | 90 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/webrick/test_httpauth.rb b/test/webrick/test_httpauth.rb index 2ee492db7a..ff539f06c7 100644 --- a/test/webrick/test_httpauth.rb +++ b/test/webrick/test_httpauth.rb @@ -4,6 +4,7 @@ require "net/http" require "tempfile" require "webrick" require "webrick/httpauth/basicauth" +require "stringio" require_relative "utils" class TestWEBrickHTTPAuth < Test::Unit::TestCase @@ -216,12 +217,97 @@ class TestWEBrickHTTPAuth < Test::Unit::TestCase } end + def test_digest_auth_int + log_tester = lambda {|log, access_log| + log.reject! {|line| /\A\s*\z/ =~ line } + pats = [ + /ERROR Digest wb auth-int realm: no credentials in the request\./, + /ERROR WEBrick::HTTPStatus::Unauthorized/, + /ERROR Digest wb auth-int realm: foo: digest unmatch\./ + ] + pats.each {|pat| + assert(!log.grep(pat).empty?, "webrick log doesn't have expected error: #{pat.inspect}") + log.reject! {|line| pat =~ line } + } + assert_equal([], log) + } + TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log| + realm = "wb auth-int realm" + path = "/digest_auth_int" + + Tempfile.create("test_webrick_auth_int") {|tmpfile| + tmpfile.close + tmp_pass = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path) + tmp_pass.set_passwd(realm, "foo", "Hunter2") + tmp_pass.flush + + htdigest = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path) + users = [] + htdigest.each{|user, pass| users << user } + assert_equal %w(foo), users + + auth = WEBrick::HTTPAuth::DigestAuth.new( + :Realm => realm, :UserDB => htdigest, + :Algorithm => 'MD5', + :Logger => server.logger, + :Qop => %w(auth-int), + ) + server.mount_proc(path){|req, res| + auth.authenticate(req, res) + res.body = "bbb" + } + Net::HTTP.start(addr, port) do |http| + post = Net::HTTP::Post.new(path) + params = {} + data = 'hello=world' + body = StringIO.new(data) + post.content_length = data.bytesize + post['Content-Type'] = 'application/x-www-form-urlencoded' + post.body_stream = body + + http.request(post) 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 + + body.rewind + cred = credentials_for_request('foo', 'Hunter3', params, body) + post['Authorization'] = cred + post.body_stream = body + http.request(post){|res| + assert_equal('401', res.code, log.call) + assert_not_equal("bbb", res.body, log.call) + } + + body.rewind + cred = credentials_for_request('foo', 'Hunter2', params, body) + post['Authorization'] = cred + post.body_stream = body + http.request(post){|res| assert_equal("bbb", res.body, log.call)} + end + } + } + end + private - def credentials_for_request(user, password, params) + def credentials_for_request(user, password, params, body = nil) cnonce = "hoge" nonce_count = 1 ha1 = "#{user}:#{params['realm']}:#{password}" - ha2 = "GET:#{params['uri']}" + if body + dig = Digest::MD5.new + while buf = body.read(16384) + dig.update(buf) + end + body.rewind + ha2 = "POST:#{params['uri']}:#{dig.hexdigest}" + else + ha2 = "GET:#{params['uri']}" + end + request_digest = "#{Digest::MD5.hexdigest(ha1)}:" \ "#{params['nonce']}:#{'%08x' % nonce_count}:#{cnonce}:#{params['qop']}:" \ -- cgit v1.2.3