webrick 1.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of webrick might be problematic. Click here for more details.

Files changed (63) hide show
  1. data/README.txt +21 -0
  2. data/lib/webrick.rb +227 -0
  3. data/lib/webrick/accesslog.rb +151 -0
  4. data/lib/webrick/cgi.rb +260 -0
  5. data/lib/webrick/compat.rb +35 -0
  6. data/lib/webrick/config.rb +121 -0
  7. data/lib/webrick/cookie.rb +110 -0
  8. data/lib/webrick/htmlutils.rb +28 -0
  9. data/lib/webrick/httpauth.rb +95 -0
  10. data/lib/webrick/httpauth/authenticator.rb +112 -0
  11. data/lib/webrick/httpauth/basicauth.rb +108 -0
  12. data/lib/webrick/httpauth/digestauth.rb +392 -0
  13. data/lib/webrick/httpauth/htdigest.rb +128 -0
  14. data/lib/webrick/httpauth/htgroup.rb +93 -0
  15. data/lib/webrick/httpauth/htpasswd.rb +121 -0
  16. data/lib/webrick/httpauth/userdb.rb +52 -0
  17. data/lib/webrick/httpproxy.rb +305 -0
  18. data/lib/webrick/httprequest.rb +461 -0
  19. data/lib/webrick/httpresponse.rb +399 -0
  20. data/lib/webrick/https.rb +64 -0
  21. data/lib/webrick/httpserver.rb +264 -0
  22. data/lib/webrick/httpservlet.rb +22 -0
  23. data/lib/webrick/httpservlet/abstract.rb +153 -0
  24. data/lib/webrick/httpservlet/cgi_runner.rb +46 -0
  25. data/lib/webrick/httpservlet/cgihandler.rb +108 -0
  26. data/lib/webrick/httpservlet/erbhandler.rb +87 -0
  27. data/lib/webrick/httpservlet/filehandler.rb +470 -0
  28. data/lib/webrick/httpservlet/prochandler.rb +33 -0
  29. data/lib/webrick/httpstatus.rb +184 -0
  30. data/lib/webrick/httputils.rb +394 -0
  31. data/lib/webrick/httpversion.rb +49 -0
  32. data/lib/webrick/log.rb +136 -0
  33. data/lib/webrick/server.rb +218 -0
  34. data/lib/webrick/ssl.rb +127 -0
  35. data/lib/webrick/utils.rb +241 -0
  36. data/lib/webrick/version.rb +13 -0
  37. data/sample/webrick/demo-app.rb +66 -0
  38. data/sample/webrick/demo-multipart.cgi +12 -0
  39. data/sample/webrick/demo-servlet.rb +6 -0
  40. data/sample/webrick/demo-urlencoded.cgi +12 -0
  41. data/sample/webrick/hello.cgi +11 -0
  42. data/sample/webrick/hello.rb +8 -0
  43. data/sample/webrick/httpd.rb +23 -0
  44. data/sample/webrick/httpproxy.rb +25 -0
  45. data/sample/webrick/httpsd.rb +33 -0
  46. data/test/openssl/utils.rb +313 -0
  47. data/test/ruby/envutil.rb +208 -0
  48. data/test/webrick/test_cgi.rb +134 -0
  49. data/test/webrick/test_cookie.rb +131 -0
  50. data/test/webrick/test_filehandler.rb +285 -0
  51. data/test/webrick/test_httpauth.rb +167 -0
  52. data/test/webrick/test_httpproxy.rb +282 -0
  53. data/test/webrick/test_httprequest.rb +411 -0
  54. data/test/webrick/test_httpresponse.rb +49 -0
  55. data/test/webrick/test_httpserver.rb +305 -0
  56. data/test/webrick/test_httputils.rb +96 -0
  57. data/test/webrick/test_httpversion.rb +40 -0
  58. data/test/webrick/test_server.rb +67 -0
  59. data/test/webrick/test_utils.rb +64 -0
  60. data/test/webrick/utils.rb +58 -0
  61. data/test/webrick/webrick.cgi +36 -0
  62. data/test/webrick/webrick_long_filename.cgi +36 -0
  63. metadata +106 -0
@@ -0,0 +1,134 @@
1
+ require_relative "utils"
2
+ require "webrick"
3
+ require "test/unit"
4
+
5
+ class TestWEBrickCGI < Test::Unit::TestCase
6
+ CRLF = "\r\n"
7
+
8
+ def start_cgi_server(&block)
9
+ config = {
10
+ :CGIInterpreter => TestWEBrick::RubyBin,
11
+ :DocumentRoot => File.dirname(__FILE__),
12
+ :DirectoryIndex => ["webrick.cgi"],
13
+ :RequestCallback => Proc.new{|req, res|
14
+ def req.meta_vars
15
+ meta = super
16
+ meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
17
+ meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV']
18
+ return meta
19
+ end
20
+ },
21
+ }
22
+ if RUBY_PLATFORM =~ /mswin32|mingw|cygwin|bccwin32/
23
+ config[:CGIPathEnv] = ENV['PATH'] # runtime dll may not be in system dir.
24
+ end
25
+ TestWEBrick.start_httpserver(config){|server, addr, port, log|
26
+ block.call(server, addr, port, log)
27
+ }
28
+ end
29
+
30
+ def test_cgi
31
+ start_cgi_server{|server, addr, port, log|
32
+ http = Net::HTTP.new(addr, port)
33
+ req = Net::HTTP::Get.new("/webrick.cgi")
34
+ http.request(req){|res| assert_equal("/webrick.cgi", res.body, log.call)}
35
+ req = Net::HTTP::Get.new("/webrick.cgi/path/info")
36
+ http.request(req){|res| assert_equal("/path/info", res.body, log.call)}
37
+ req = Net::HTTP::Get.new("/webrick.cgi/%3F%3F%3F?foo=bar")
38
+ http.request(req){|res| assert_equal("/???", res.body, log.call)}
39
+ req = Net::HTTP::Get.new("/webrick.cgi/%A4%DB%A4%B2/%A4%DB%A4%B2")
40
+ http.request(req){|res|
41
+ assert_equal("/\xA4\xDB\xA4\xB2/\xA4\xDB\xA4\xB2", res.body, log.call)}
42
+ req = Net::HTTP::Get.new("/webrick.cgi?a=1;a=2;b=x")
43
+ http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
44
+ req = Net::HTTP::Get.new("/webrick.cgi?a=1&a=2&b=x")
45
+ http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
46
+
47
+ req = Net::HTTP::Post.new("/webrick.cgi?a=x;a=y;b=1")
48
+ req["Content-Type"] = "application/x-www-form-urlencoded"
49
+ http.request(req, "a=1;a=2;b=x"){|res|
50
+ assert_equal("a=1, a=2, b=x", res.body, log.call)}
51
+ req = Net::HTTP::Post.new("/webrick.cgi?a=x&a=y&b=1")
52
+ req["Content-Type"] = "application/x-www-form-urlencoded"
53
+ http.request(req, "a=1&a=2&b=x"){|res|
54
+ assert_equal("a=1, a=2, b=x", res.body, log.call)}
55
+ req = Net::HTTP::Get.new("/")
56
+ http.request(req){|res|
57
+ ary = res.body.lines.to_a
58
+ assert_match(%r{/$}, ary[0], log.call)
59
+ assert_match(%r{/webrick.cgi$}, ary[1], log.call)
60
+ }
61
+
62
+ req = Net::HTTP::Get.new("/webrick.cgi")
63
+ req["Cookie"] = "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001"
64
+ http.request(req){|res|
65
+ assert_equal(
66
+ "CUSTOMER=WILE_E_COYOTE\nPART_NUMBER=ROCKET_LAUNCHER_0001\n",
67
+ res.body, log.call)
68
+ }
69
+
70
+ req = Net::HTTP::Get.new("/webrick.cgi")
71
+ cookie = %{$Version="1"; }
72
+ cookie << %{Customer="WILE_E_COYOTE"; $Path="/acme"; }
73
+ cookie << %{Part_Number="Rocket_Launcher_0001"; $Path="/acme"; }
74
+ cookie << %{Shipping="FedEx"; $Path="/acme"}
75
+ req["Cookie"] = cookie
76
+ http.request(req){|res|
77
+ assert_equal("Customer=WILE_E_COYOTE, Shipping=FedEx",
78
+ res["Set-Cookie"], log.call)
79
+ assert_equal("Customer=WILE_E_COYOTE\n" +
80
+ "Part_Number=Rocket_Launcher_0001\n" +
81
+ "Shipping=FedEx\n", res.body, log.call)
82
+ }
83
+ }
84
+ end
85
+
86
+ def test_bad_request
87
+ start_cgi_server{|server, addr, port, log|
88
+ sock = TCPSocket.new(addr, port)
89
+ begin
90
+ sock << "POST /webrick.cgi HTTP/1.0" << CRLF
91
+ sock << "Content-Type: application/x-www-form-urlencoded" << CRLF
92
+ sock << "Content-Length: 1024" << CRLF
93
+ sock << CRLF
94
+ sock << "a=1&a=2&b=x"
95
+ sock.close_write
96
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, sock.read, log.call)
97
+ ensure
98
+ sock.close
99
+ end
100
+ }
101
+ end
102
+
103
+ CtrlSeq = [0x7f, *(1..31)].pack("C*").gsub(/\s+/, '')
104
+ CtrlPat = /#{Regexp.quote(CtrlSeq)}/o
105
+ DumpPat = /#{Regexp.quote(CtrlSeq.dump[1...-1])}/o
106
+
107
+ def test_bad_uri
108
+ start_cgi_server{|server, addr, port, log|
109
+ res = TCPSocket.open(addr, port) {|sock|
110
+ sock << "GET /#{CtrlSeq}#{CRLF}#{CRLF}"
111
+ sock.close_write
112
+ sock.read
113
+ }
114
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, res)
115
+ s = log.call.each_line.grep(/ERROR bad URI/)[0]
116
+ assert_match(DumpPat, s)
117
+ assert_not_match(CtrlPat, s)
118
+ }
119
+ end
120
+
121
+ def test_bad_header
122
+ start_cgi_server{|server, addr, port, log|
123
+ res = TCPSocket.open(addr, port) {|sock|
124
+ sock << "GET / HTTP/1.0#{CRLF}#{CtrlSeq}#{CRLF}#{CRLF}"
125
+ sock.close_write
126
+ sock.read
127
+ }
128
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, res)
129
+ s = log.call.each_line.grep(/ERROR bad header/)[0]
130
+ assert_match(DumpPat, s)
131
+ assert_not_match(CtrlPat, s)
132
+ }
133
+ end
134
+ end
@@ -0,0 +1,131 @@
1
+ require "test/unit"
2
+ require "webrick/cookie"
3
+
4
+ class TestWEBrickCookie < Test::Unit::TestCase
5
+ def test_new
6
+ cookie = WEBrick::Cookie.new("foo","bar")
7
+ assert_equal("foo", cookie.name)
8
+ assert_equal("bar", cookie.value)
9
+ assert_equal("foo=bar", cookie.to_s)
10
+ end
11
+
12
+ def test_time
13
+ cookie = WEBrick::Cookie.new("foo","bar")
14
+ t = 1000000000
15
+ cookie.max_age = t
16
+ assert_match(t.to_s, cookie.to_s)
17
+
18
+ cookie = WEBrick::Cookie.new("foo","bar")
19
+ t = Time.at(1000000000)
20
+ cookie.expires = t
21
+ assert_equal(Time, cookie.expires.class)
22
+ assert_equal(t, cookie.expires)
23
+ ts = t.httpdate
24
+ cookie.expires = ts
25
+ assert_equal(Time, cookie.expires.class)
26
+ assert_equal(t, cookie.expires)
27
+ assert_match(ts, cookie.to_s)
28
+ end
29
+
30
+ def test_parse
31
+ data = ""
32
+ data << '$Version="1"; '
33
+ data << 'Customer="WILE_E_COYOTE"; $Path="/acme"; '
34
+ data << 'Part_Number="Rocket_Launcher_0001"; $Path="/acme"; '
35
+ data << 'Shipping="FedEx"; $Path="/acme"'
36
+ cookies = WEBrick::Cookie.parse(data)
37
+ assert_equal(3, cookies.size)
38
+ assert_equal(1, cookies[0].version)
39
+ assert_equal("Customer", cookies[0].name)
40
+ assert_equal("WILE_E_COYOTE", cookies[0].value)
41
+ assert_equal("/acme", cookies[0].path)
42
+ assert_equal(1, cookies[1].version)
43
+ assert_equal("Part_Number", cookies[1].name)
44
+ assert_equal("Rocket_Launcher_0001", cookies[1].value)
45
+ assert_equal(1, cookies[2].version)
46
+ assert_equal("Shipping", cookies[2].name)
47
+ assert_equal("FedEx", cookies[2].value)
48
+
49
+ data = "hoge=moge; __div__session=9865ecfd514be7f7"
50
+ cookies = WEBrick::Cookie.parse(data)
51
+ assert_equal(0, cookies[0].version)
52
+ assert_equal("hoge", cookies[0].name)
53
+ assert_equal("moge", cookies[0].value)
54
+ assert_equal("__div__session", cookies[1].name)
55
+ assert_equal("9865ecfd514be7f7", cookies[1].value)
56
+ end
57
+
58
+ def test_parse_no_whitespace
59
+ data = [
60
+ '$Version="1"; ',
61
+ 'Customer="WILE_E_COYOTE";$Path="/acme";', # no SP between cookie-string
62
+ 'Part_Number="Rocket_Launcher_0001";$Path="/acme";', # no SP between cookie-string
63
+ 'Shipping="FedEx";$Path="/acme"'
64
+ ].join
65
+ cookies = WEBrick::Cookie.parse(data)
66
+ assert_equal(1, cookies.size)
67
+ end
68
+
69
+ def test_parse_too_much_whitespaces
70
+ # According to RFC6265,
71
+ # cookie-string = cookie-pair *( ";" SP cookie-pair )
72
+ # So single 0x20 is needed after ';'. We allow multiple spaces here for
73
+ # compatibility with older WEBrick versions.
74
+ data = [
75
+ '$Version="1"; ',
76
+ 'Customer="WILE_E_COYOTE";$Path="/acme"; ', # no SP between cookie-string
77
+ 'Part_Number="Rocket_Launcher_0001";$Path="/acme"; ', # no SP between cookie-string
78
+ 'Shipping="FedEx";$Path="/acme"'
79
+ ].join
80
+ cookies = WEBrick::Cookie.parse(data)
81
+ assert_equal(3, cookies.size)
82
+ end
83
+
84
+ def test_parse_set_cookie
85
+ data = %(Customer="WILE_E_COYOTE"; Version="1"; Path="/acme")
86
+ cookie = WEBrick::Cookie.parse_set_cookie(data)
87
+ assert_equal("Customer", cookie.name)
88
+ assert_equal("WILE_E_COYOTE", cookie.value)
89
+ assert_equal(1, cookie.version)
90
+ assert_equal("/acme", cookie.path)
91
+
92
+ data = %(Shipping="FedEx"; Version="1"; Path="/acme"; Secure)
93
+ cookie = WEBrick::Cookie.parse_set_cookie(data)
94
+ assert_equal("Shipping", cookie.name)
95
+ assert_equal("FedEx", cookie.value)
96
+ assert_equal(1, cookie.version)
97
+ assert_equal("/acme", cookie.path)
98
+ assert_equal(true, cookie.secure)
99
+ end
100
+
101
+ def test_parse_set_cookies
102
+ data = %(Shipping="FedEx"; Version="1"; Path="/acme"; Secure)
103
+ data << %(, CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT; path=/; Secure)
104
+ data << %(, name="Aaron"; Version="1"; path="/acme")
105
+ cookies = WEBrick::Cookie.parse_set_cookies(data)
106
+ assert_equal(3, cookies.length)
107
+
108
+ fed_ex = cookies.find { |c| c.name == 'Shipping' }
109
+ assert_not_nil(fed_ex)
110
+ assert_equal("Shipping", fed_ex.name)
111
+ assert_equal("FedEx", fed_ex.value)
112
+ assert_equal(1, fed_ex.version)
113
+ assert_equal("/acme", fed_ex.path)
114
+ assert_equal(true, fed_ex.secure)
115
+
116
+ name = cookies.find { |c| c.name == 'name' }
117
+ assert_not_nil(name)
118
+ assert_equal("name", name.name)
119
+ assert_equal("Aaron", name.value)
120
+ assert_equal(1, name.version)
121
+ assert_equal("/acme", name.path)
122
+
123
+ customer = cookies.find { |c| c.name == 'CUSTOMER' }
124
+ assert_not_nil(customer)
125
+ assert_equal("CUSTOMER", customer.name)
126
+ assert_equal("WILE_E_COYOTE", customer.value)
127
+ assert_equal(0, customer.version)
128
+ assert_equal("/", customer.path)
129
+ assert_equal(Time.utc(1999, 11, 9, 23, 12, 40), customer.expires)
130
+ end
131
+ end
@@ -0,0 +1,285 @@
1
+ require "test/unit"
2
+ require_relative "utils.rb"
3
+ require "webrick"
4
+ require "stringio"
5
+
6
+ class WEBrick::TestFileHandler < Test::Unit::TestCase
7
+ def default_file_handler(filename)
8
+ klass = WEBrick::HTTPServlet::DefaultFileHandler
9
+ klass.new(WEBrick::Config::HTTP, filename)
10
+ end
11
+
12
+ def windows?
13
+ File.directory?("\\")
14
+ end
15
+
16
+ def get_res_body(res)
17
+ if defined? res.body.read
18
+ res.body.read
19
+ else
20
+ res.body
21
+ end
22
+ end
23
+
24
+ def make_range_request(range_spec)
25
+ msg = <<-END_OF_REQUEST
26
+ GET / HTTP/1.0
27
+ Range: #{range_spec}
28
+
29
+ END_OF_REQUEST
30
+ return StringIO.new(msg.gsub(/^ {6}/, ""))
31
+ end
32
+
33
+ def make_range_response(file, range_spec)
34
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
35
+ req.parse(make_range_request(range_spec))
36
+ res = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
37
+ size = File.size(file)
38
+ handler = default_file_handler(file)
39
+ handler.make_partial_content(req, res, file, size)
40
+ return res
41
+ end
42
+
43
+ def test_make_partial_content
44
+ filename = __FILE__
45
+ filesize = File.size(filename)
46
+
47
+ res = make_range_response(filename, "bytes=#{filesize-100}-")
48
+ assert_match(%r{^text/plain}, res["content-type"])
49
+ assert_equal(get_res_body(res).size, 100)
50
+
51
+ res = make_range_response(filename, "bytes=-100")
52
+ assert_match(%r{^text/plain}, res["content-type"])
53
+ assert_equal(get_res_body(res).size, 100)
54
+
55
+ res = make_range_response(filename, "bytes=0-99")
56
+ assert_match(%r{^text/plain}, res["content-type"])
57
+ assert_equal(get_res_body(res).size, 100)
58
+
59
+ res = make_range_response(filename, "bytes=100-199")
60
+ assert_match(%r{^text/plain}, res["content-type"])
61
+ assert_equal(get_res_body(res).size, 100)
62
+
63
+ res = make_range_response(filename, "bytes=0-0")
64
+ assert_match(%r{^text/plain}, res["content-type"])
65
+ assert_equal(get_res_body(res).size, 1)
66
+
67
+ res = make_range_response(filename, "bytes=-1")
68
+ assert_match(%r{^text/plain}, res["content-type"])
69
+ assert_equal(get_res_body(res).size, 1)
70
+
71
+ res = make_range_response(filename, "bytes=0-0, -2")
72
+ assert_match(%r{^multipart/byteranges}, res["content-type"])
73
+ end
74
+
75
+ def test_filehandler
76
+ config = { :DocumentRoot => File.dirname(__FILE__), }
77
+ this_file = File.basename(__FILE__)
78
+ filesize = File.size(__FILE__)
79
+ this_data = File.open(__FILE__, "rb") {|f| f.read}
80
+ range = nil
81
+ bug2593 = '[ruby-dev:40030]'
82
+
83
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
84
+ http = Net::HTTP.new(addr, port)
85
+ req = Net::HTTP::Get.new("/")
86
+ http.request(req){|res|
87
+ assert_equal("200", res.code, log.call)
88
+ assert_equal("text/html", res.content_type, log.call)
89
+ assert_match(/HREF="#{this_file}"/, res.body, log.call)
90
+ }
91
+ req = Net::HTTP::Get.new("/#{this_file}")
92
+ http.request(req){|res|
93
+ assert_equal("200", res.code, log.call)
94
+ assert_equal("text/plain", res.content_type, log.call)
95
+ assert_equal(File.read(__FILE__), res.body, log.call)
96
+ }
97
+
98
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=#{filesize-100}-")
99
+ http.request(req){|res|
100
+ assert_equal("206", res.code, log.call)
101
+ assert_equal("text/plain", res.content_type, log.call)
102
+ assert_nothing_raised(bug2593) {range = res.content_range}
103
+ assert_equal((filesize-100)..(filesize-1), range, log.call)
104
+ assert_equal(this_data[-100..-1], res.body, log.call)
105
+ }
106
+
107
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-100")
108
+ http.request(req){|res|
109
+ assert_equal("206", res.code, log.call)
110
+ assert_equal("text/plain", res.content_type, log.call)
111
+ assert_nothing_raised(bug2593) {range = res.content_range}
112
+ assert_equal((filesize-100)..(filesize-1), range, log.call)
113
+ assert_equal(this_data[-100..-1], res.body, log.call)
114
+ }
115
+
116
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-99")
117
+ http.request(req){|res|
118
+ assert_equal("206", res.code, log.call)
119
+ assert_equal("text/plain", res.content_type, log.call)
120
+ assert_nothing_raised(bug2593) {range = res.content_range}
121
+ assert_equal(0..99, range, log.call)
122
+ assert_equal(this_data[0..99], res.body, log.call)
123
+ }
124
+
125
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=100-199")
126
+ http.request(req){|res|
127
+ assert_equal("206", res.code, log.call)
128
+ assert_equal("text/plain", res.content_type, log.call)
129
+ assert_nothing_raised(bug2593) {range = res.content_range}
130
+ assert_equal(100..199, range, log.call)
131
+ assert_equal(this_data[100..199], res.body, log.call)
132
+ }
133
+
134
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0")
135
+ http.request(req){|res|
136
+ assert_equal("206", res.code, log.call)
137
+ assert_equal("text/plain", res.content_type, log.call)
138
+ assert_nothing_raised(bug2593) {range = res.content_range}
139
+ assert_equal(0..0, range, log.call)
140
+ assert_equal(this_data[0..0], res.body, log.call)
141
+ }
142
+
143
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-1")
144
+ http.request(req){|res|
145
+ assert_equal("206", res.code, log.call)
146
+ assert_equal("text/plain", res.content_type, log.call)
147
+ assert_nothing_raised(bug2593) {range = res.content_range}
148
+ assert_equal((filesize-1)..(filesize-1), range, log.call)
149
+ assert_equal(this_data[-1, 1], res.body, log.call)
150
+ }
151
+
152
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0, -2")
153
+ http.request(req){|res|
154
+ assert_equal("206", res.code, log.call)
155
+ assert_equal("multipart/byteranges", res.content_type, log.call)
156
+ }
157
+
158
+ end
159
+ end
160
+
161
+ def test_non_disclosure_name
162
+ config = { :DocumentRoot => File.dirname(__FILE__), }
163
+ this_file = File.basename(__FILE__)
164
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
165
+ http = Net::HTTP.new(addr, port)
166
+ doc_root_opts = server[:DocumentRootOptions]
167
+ doc_root_opts[:NondisclosureName] = %w(.ht* *~ test_*)
168
+ req = Net::HTTP::Get.new("/")
169
+ http.request(req){|res|
170
+ assert_equal("200", res.code, log.call)
171
+ assert_equal("text/html", res.content_type, log.call)
172
+ assert_no_match(/HREF="#{File.basename(__FILE__)}"/, res.body)
173
+ }
174
+ req = Net::HTTP::Get.new("/#{this_file}")
175
+ http.request(req){|res|
176
+ assert_equal("404", res.code, log.call)
177
+ }
178
+ doc_root_opts[:NondisclosureName] = %w(.ht* *~ TEST_*)
179
+ http.request(req){|res|
180
+ assert_equal("404", res.code, log.call)
181
+ }
182
+ end
183
+ end
184
+
185
+ def test_directory_traversal
186
+ config = { :DocumentRoot => File.dirname(__FILE__), }
187
+ this_file = File.basename(__FILE__)
188
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
189
+ http = Net::HTTP.new(addr, port)
190
+ req = Net::HTTP::Get.new("/../../")
191
+ http.request(req){|res| assert_equal("400", res.code, log.call) }
192
+ req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}")
193
+ http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code, log.call) }
194
+ req = Net::HTTP::Get.new("/..%5c..%5cruby.c")
195
+ http.request(req){|res| assert_equal("404", res.code, log.call) }
196
+ end
197
+ end
198
+
199
+ def test_unwise_in_path
200
+ if windows?
201
+ config = { :DocumentRoot => File.dirname(__FILE__), }
202
+ this_file = File.basename(__FILE__)
203
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
204
+ http = Net::HTTP.new(addr, port)
205
+ req = Net::HTTP::Get.new("/..%5c..")
206
+ http.request(req){|res| assert_equal("301", res.code, log.call) }
207
+ end
208
+ end
209
+ end
210
+
211
+ def test_short_filename
212
+ config = {
213
+ :CGIInterpreter => TestWEBrick::RubyBin,
214
+ :DocumentRoot => File.dirname(__FILE__),
215
+ :CGIPathEnv => ENV['PATH'],
216
+ }
217
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
218
+ http = Net::HTTP.new(addr, port)
219
+ if windows?
220
+ fname = nil
221
+ Dir.chdir(config[:DocumentRoot]) do
222
+ fname = IO.popen("dir /x webrick_long_filename.cgi", "r").read.match(/\s(w.+?cgi)\s/i)[1].downcase
223
+ end
224
+ else
225
+ fname = "webric~1.cgi"
226
+ end
227
+ req = Net::HTTP::Get.new("/#{fname}/test")
228
+ http.request(req) do |res|
229
+ if windows?
230
+ assert_equal("200", res.code, log.call)
231
+ assert_equal("/test", res.body, log.call)
232
+ else
233
+ assert_equal("404", res.code, log.call)
234
+ end
235
+ end
236
+
237
+ req = Net::HTTP::Get.new("/.htaccess")
238
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
239
+ req = Net::HTTP::Get.new("/htacce~1")
240
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
241
+ req = Net::HTTP::Get.new("/HTACCE~1")
242
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
243
+ end
244
+ end
245
+
246
+ def test_script_disclosure
247
+ config = {
248
+ :CGIInterpreter => TestWEBrick::RubyBin,
249
+ :DocumentRoot => File.dirname(__FILE__),
250
+ :CGIPathEnv => ENV['PATH'],
251
+ :RequestCallback => Proc.new{|req, res|
252
+ def req.meta_vars
253
+ meta = super
254
+ meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
255
+ meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV']
256
+ return meta
257
+ end
258
+ },
259
+ }
260
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
261
+ http = Net::HTTP.new(addr, port)
262
+
263
+ req = Net::HTTP::Get.new("/webrick.cgi/test")
264
+ http.request(req) do |res|
265
+ assert_equal("200", res.code, log.call)
266
+ assert_equal("/test", res.body, log.call)
267
+ end
268
+
269
+ response_assertion = Proc.new do |res|
270
+ if windows?
271
+ assert_equal("200", res.code, log.call)
272
+ assert_equal("/test", res.body, log.call)
273
+ else
274
+ assert_equal("404", res.code, log.call)
275
+ end
276
+ end
277
+ req = Net::HTTP::Get.new("/webrick.cgi%20/test")
278
+ http.request(req, &response_assertion)
279
+ req = Net::HTTP::Get.new("/webrick.cgi./test")
280
+ http.request(req, &response_assertion)
281
+ req = Net::HTTP::Get.new("/webrick.cgi::$DATA/test")
282
+ http.request(req, &response_assertion)
283
+ end
284
+ end
285
+ end