summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-28 09:26:13 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-28 09:26:13 +0000
commita1c9ee2b0b4bf0f0912e0ba8b566ba28aa2cf2f1 (patch)
tree4429511f69b79764f6b5f5d34cdbf7e15ad81cfe
parent18b99e2a0a9a21ba619404905e181191e46b09bc (diff)
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
-rw-r--r--test/webrick/test_httpauth.rb90
1 files changed, 88 insertions, 2 deletions
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']}:" \