summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-07-26 03:21:52 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-07-26 03:21:52 +0000
commit9749bfbf735f8dca3361f2ea16bb97027bd1ab61 (patch)
treecca1f10d0971f7721cd06e3867ba4acaea57bc14 /test
parent1516b85d54d23097138b384a6364ca36d00cbad4 (diff)
webrick: Support bcrypt password hashing
This adds a password_hash keyword argument to WEBrick::HTTPAuth::Htpasswd#initialize. If set to :bcrypt, it will create bcrypt hashes instead of crypt hashes, and will raise an exception if the .htpasswd file uses crypt hashes. If :bcrypt is used, then instead of calling BasicAuth.make_passwd (which uses crypt), WEBrick::HTTPAuth::Htpasswd#set_passwd will set the bcrypt password directly. It isn't possible to change the make_passwd API to accept the password hash format, as that would break configurations who use Htpasswd#auth_type= to set a custom auth_type. This modifies WEBrick::HTTPAuth::BasicAuth to handle checking both crypt and bcrypt hashes. There are commented out requires for 'string/crypt', to handle when String#crypt is deprecated and the undeprecated version is moved to a gem. There is also a commented out warning for the case when the password_hash keyword is not specified and 'string/crypt' cannot be required. I think the warning makes sense to nudge users to using bcrypt. I've updated the tests to test nil, :crypt, and :bcrypt values for the password_hash keyword, skipping the bcrypt tests if the bcrypt library cannot be required. [ruby-core:88111] [Feature #14940] From: Jeremy Evans <code@jeremyevans.net> git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64060 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test')
-rw-r--r--test/webrick/test_httpauth.rb175
1 files changed, 95 insertions, 80 deletions
diff --git a/test/webrick/test_httpauth.rb b/test/webrick/test_httpauth.rb
index 8439be2025..dcf74689e1 100644
--- a/test/webrick/test_httpauth.rb
+++ b/test/webrick/test_httpauth.rb
@@ -37,56 +37,7 @@ class TestWEBrickHTTPAuth < Test::Unit::TestCase
}
end
- def test_basic_auth2
- log_tester = lambda {|log, access_log|
- log.reject! {|line| /\A\s*\z/ =~ line }
- pats = [
- /ERROR Basic WEBrick's realm: webrick: password unmatch\./,
- /ERROR WEBrick::HTTPStatus::Unauthorized/
- ]
- 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 = "WEBrick's realm"
- path = "/basic_auth2"
-
- Tempfile.create("test_webrick_auth") {|tmpfile|
- tmpfile.close
- tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
- tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
- tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
- tmp_pass.flush
-
- htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
- users = []
- htpasswd.each{|user, pass| users << user }
- assert_equal(2, users.size, log.call)
- assert(users.member?("webrick"), log.call)
- assert(users.member?("foo"), log.call)
-
- server.mount_proc(path){|req, res|
- auth = WEBrick::HTTPAuth::BasicAuth.new(
- :Realm => realm, :UserDB => htpasswd,
- :Logger => server.logger
- )
- auth.authenticate(req, res)
- res.body = "hoge"
- }
- http = Net::HTTP.new(addr, port)
- g = Net::HTTP::Get.new(path)
- g.basic_auth("webrick", "supersecretpassword")
- http.request(g){|res| assert_equal("hoge", res.body, log.call)}
- g.basic_auth("webrick", "not super")
- http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
- }
- }
- end
-
- def test_basic_auth3
+ def test_basic_auth_sha
Tempfile.create("test_webrick_auth") {|tmpfile|
tmpfile.puts("webrick:{SHA}GJYFRpBbdchp595jlh3Bhfmgp8k=")
tmpfile.flush
@@ -94,7 +45,9 @@ class TestWEBrickHTTPAuth < Test::Unit::TestCase
WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
}
}
+ end
+ def test_basic_auth_md5
Tempfile.create("test_webrick_auth") {|tmpfile|
tmpfile.puts("webrick:$apr1$IOVMD/..$rmnOSPXr0.wwrLPZHBQZy0")
tmpfile.flush
@@ -104,40 +57,102 @@ class TestWEBrickHTTPAuth < Test::Unit::TestCase
}
end
- def test_bad_username_with_control_characters
- log_tester = lambda {|log, access_log|
- assert_equal(2, log.length)
- assert_match(/ERROR Basic WEBrick's realm: foo\\ebar: the user is not allowed./, log[0])
- assert_match(/ERROR WEBrick::HTTPStatus::Unauthorized/, log[1])
- }
- TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log|
- realm = "WEBrick's realm"
- path = "/basic_auth"
+ [nil, :crypt, :bcrypt].each do |hash_algo|
+ begin
+ case hash_algo
+ when :crypt
+ # require 'string/crypt'
+ when :bcrypt
+ require 'bcrypt'
+ end
+ rescue LoadError
+ next
+ end
- Tempfile.create("test_webrick_auth") {|tmpfile|
- tmpfile.close
- tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
- tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
- tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
- tmp_pass.flush
+ define_method(:"test_basic_auth_htpasswd_#{hash_algo}") do
+ log_tester = lambda {|log, access_log|
+ log.reject! {|line| /\A\s*\z/ =~ line }
+ pats = [
+ /ERROR Basic WEBrick's realm: webrick: password unmatch\./,
+ /ERROR WEBrick::HTTPStatus::Unauthorized/
+ ]
+ 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 = "WEBrick's realm"
+ path = "/basic_auth2"
- htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
- users = []
- htpasswd.each{|user, pass| users << user }
- server.mount_proc(path){|req, res|
- auth = WEBrick::HTTPAuth::BasicAuth.new(
- :Realm => realm, :UserDB => htpasswd,
- :Logger => server.logger
- )
- auth.authenticate(req, res)
- res.body = "hoge"
+ Tempfile.create("test_webrick_auth") {|tmpfile|
+ tmpfile.close
+ tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path, password_hash: hash_algo)
+ tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
+ tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
+ tmp_pass.flush
+
+ htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path, password_hash: hash_algo)
+ users = []
+ htpasswd.each{|user, pass| users << user }
+ assert_equal(2, users.size, log.call)
+ assert(users.member?("webrick"), log.call)
+ assert(users.member?("foo"), log.call)
+
+ server.mount_proc(path){|req, res|
+ auth = WEBrick::HTTPAuth::BasicAuth.new(
+ :Realm => realm, :UserDB => htpasswd,
+ :Logger => server.logger
+ )
+ auth.authenticate(req, res)
+ res.body = "hoge"
+ }
+ http = Net::HTTP.new(addr, port)
+ g = Net::HTTP::Get.new(path)
+ g.basic_auth("webrick", "supersecretpassword")
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
+ g.basic_auth("webrick", "not super")
+ http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
}
- http = Net::HTTP.new(addr, port)
- g = Net::HTTP::Get.new(path)
- g.basic_auth("foo\ebar", "passwd")
- http.request(g){|res| assert_not_equal("hoge", res.body, log.call) }
}
- }
+ end
+
+ define_method(:"test_basic_auth_bad_username_htpasswd_#{hash_algo}") do
+ log_tester = lambda {|log, access_log|
+ assert_equal(2, log.length)
+ assert_match(/ERROR Basic WEBrick's realm: foo\\ebar: the user is not allowed./, log[0])
+ assert_match(/ERROR WEBrick::HTTPStatus::Unauthorized/, log[1])
+ }
+ TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log|
+ realm = "WEBrick's realm"
+ path = "/basic_auth"
+
+ Tempfile.create("test_webrick_auth") {|tmpfile|
+ tmpfile.close
+ tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path, password_hash: hash_algo)
+ tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
+ tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
+ tmp_pass.flush
+
+ htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path, password_hash: hash_algo)
+ users = []
+ htpasswd.each{|user, pass| users << user }
+ server.mount_proc(path){|req, res|
+ auth = WEBrick::HTTPAuth::BasicAuth.new(
+ :Realm => realm, :UserDB => htpasswd,
+ :Logger => server.logger
+ )
+ auth.authenticate(req, res)
+ res.body = "hoge"
+ }
+ http = Net::HTTP.new(addr, port)
+ g = Net::HTTP::Get.new(path)
+ g.basic_auth("foo\ebar", "passwd")
+ http.request(g){|res| assert_not_equal("hoge", res.body, log.call) }
+ }
+ }
+ end
end
DIGESTRES_ = /