webrick 1.4.0.beta1 → 1.4.4
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.
- checksums.yaml +5 -5
- data/lib/webrick/cgi.rb +7 -3
- data/lib/webrick/config.rb +5 -5
- data/lib/webrick/cookie.rb +1 -1
- data/lib/webrick/httpauth.rb +5 -5
- data/lib/webrick/httpauth/basicauth.rb +13 -5
- data/lib/webrick/httpauth/digestauth.rb +10 -23
- data/lib/webrick/httpauth/htdigest.rb +4 -4
- data/lib/webrick/httpauth/htgroup.rb +9 -6
- data/lib/webrick/httpauth/htpasswd.rb +39 -6
- data/lib/webrick/httpproxy.rb +48 -36
- data/lib/webrick/httprequest.rb +53 -14
- data/lib/webrick/httpresponse.rb +97 -49
- data/lib/webrick/https.rb +66 -1
- data/lib/webrick/httpserver.rb +25 -11
- data/lib/webrick/httpservlet.rb +5 -5
- data/lib/webrick/httpservlet/abstract.rb +3 -5
- data/lib/webrick/httpservlet/cgi_runner.rb +2 -2
- data/lib/webrick/httpservlet/cgihandler.rb +3 -5
- data/lib/webrick/httpservlet/erbhandler.rb +2 -2
- data/lib/webrick/httpservlet/filehandler.rb +49 -31
- data/lib/webrick/httpservlet/prochandler.rb +1 -1
- data/lib/webrick/httpstatus.rb +1 -5
- data/lib/webrick/httputils.rb +3 -0
- data/lib/webrick/log.rb +3 -3
- data/lib/webrick/server.rb +34 -17
- data/lib/webrick/ssl.rb +20 -7
- data/lib/webrick/utils.rb +1 -2
- data/lib/webrick/version.rb +1 -1
- metadata +17 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a3c66cf23e2b33e288598d3f59d9e56ca97e465835a68829fb2618938563ad87
|
4
|
+
data.tar.gz: 99c190d49011abfab1f528cf59a6fb4135c6877c1a49a56b69798143ab9d7849
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acca7540bda5156d247c6e0a94ed686366ce65fb0b83115667653311d28c2e105729f7f729253b2c382c5f9098c324443b3bdf077b89fffb5f0c8b96342c16dd
|
7
|
+
data.tar.gz: 20a40ff73c5372bc0453a871fe15ffe4f8ec3e53862eccabfb2849b9b5d275bc22ebba48fe4cf7cac3fcfeff30bb5d1619f6f77efcd53f189803f2ec237adf8d
|
data/lib/webrick/cgi.rb
CHANGED
@@ -8,9 +8,9 @@
|
|
8
8
|
#
|
9
9
|
# $Id$
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
require_relative "httprequest"
|
12
|
+
require_relative "httpresponse"
|
13
|
+
require_relative "config"
|
14
14
|
require "stringio"
|
15
15
|
|
16
16
|
module WEBrick
|
@@ -265,6 +265,10 @@ module WEBrick
|
|
265
265
|
@out_port << data
|
266
266
|
end
|
267
267
|
|
268
|
+
def write(data)
|
269
|
+
@out_port.write(data)
|
270
|
+
end
|
271
|
+
|
268
272
|
def cert
|
269
273
|
return nil unless defined?(OpenSSL)
|
270
274
|
if pem = @env["SSL_SERVER_CERT"]
|
data/lib/webrick/config.rb
CHANGED
@@ -9,11 +9,11 @@
|
|
9
9
|
#
|
10
10
|
# $IPR: config.rb,v 1.52 2003/07/22 19:20:42 gotoyuzo Exp $
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
require_relative 'version'
|
13
|
+
require_relative 'httpversion'
|
14
|
+
require_relative 'httputils'
|
15
|
+
require_relative 'utils'
|
16
|
+
require_relative 'log'
|
17
17
|
|
18
18
|
module WEBrick
|
19
19
|
module Config
|
data/lib/webrick/cookie.rb
CHANGED
data/lib/webrick/httpauth.rb
CHANGED
@@ -9,11 +9,11 @@
|
|
9
9
|
#
|
10
10
|
# $IPR: httpauth.rb,v 1.14 2003/07/22 19:20:42 gotoyuzo Exp $
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
require_relative 'httpauth/basicauth'
|
13
|
+
require_relative 'httpauth/digestauth'
|
14
|
+
require_relative 'httpauth/htpasswd'
|
15
|
+
require_relative 'httpauth/htdigest'
|
16
|
+
require_relative 'httpauth/htgroup'
|
17
17
|
|
18
18
|
module WEBrick
|
19
19
|
|
@@ -8,9 +8,9 @@
|
|
8
8
|
#
|
9
9
|
# $IPR: basicauth.rb,v 1.5 2003/02/20 07:15:47 gotoyuzo Exp $
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
require_relative '../config'
|
12
|
+
require_relative '../httpstatus'
|
13
|
+
require_relative 'authenticator'
|
14
14
|
|
15
15
|
module WEBrick
|
16
16
|
module HTTPAuth
|
@@ -24,7 +24,7 @@ module WEBrick
|
|
24
24
|
#
|
25
25
|
# config = { :Realm => 'BasicAuth example realm' }
|
26
26
|
#
|
27
|
-
# htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file'
|
27
|
+
# htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file', password_hash: :bcrypt
|
28
28
|
# htpasswd.set_passwd config[:Realm], 'username', 'password'
|
29
29
|
# htpasswd.flush
|
30
30
|
#
|
@@ -81,7 +81,15 @@ module WEBrick
|
|
81
81
|
error("%s: the user is not allowed.", userid)
|
82
82
|
challenge(req, res)
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
|
+
case encpass
|
86
|
+
when /\A\$2[aby]\$/
|
87
|
+
password_matches = BCrypt::Password.new(encpass.sub(/\A\$2[aby]\$/, '$2a$')) == password
|
88
|
+
else
|
89
|
+
password_matches = password.crypt(encpass) == encpass
|
90
|
+
end
|
91
|
+
|
92
|
+
unless password_matches
|
85
93
|
error("%s: password unmatch.", userid)
|
86
94
|
challenge(req, res)
|
87
95
|
end
|
@@ -12,9 +12,9 @@
|
|
12
12
|
#
|
13
13
|
# $IPR: digestauth.rb,v 1.5 2003/02/20 07:15:47 gotoyuzo Exp $
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
require_relative '../config'
|
16
|
+
require_relative '../httpstatus'
|
17
|
+
require_relative 'authenticator'
|
18
18
|
require 'digest/md5'
|
19
19
|
require 'digest/sha1'
|
20
20
|
|
@@ -235,9 +235,11 @@ module WEBrick
|
|
235
235
|
ha2 = hexdigest(req.request_method, auth_req['uri'])
|
236
236
|
ha2_res = hexdigest("", auth_req['uri'])
|
237
237
|
elsif auth_req['qop'] == "auth-int"
|
238
|
-
|
239
|
-
|
240
|
-
|
238
|
+
body_digest = @h.new
|
239
|
+
req.body { |chunk| body_digest.update(chunk) }
|
240
|
+
body_digest = body_digest.hexdigest
|
241
|
+
ha2 = hexdigest(req.request_method, auth_req['uri'], body_digest)
|
242
|
+
ha2_res = hexdigest("", auth_req['uri'], body_digest)
|
241
243
|
end
|
242
244
|
|
243
245
|
if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int"
|
@@ -288,23 +290,8 @@ module WEBrick
|
|
288
290
|
|
289
291
|
def split_param_value(string)
|
290
292
|
ret = {}
|
291
|
-
|
292
|
-
|
293
|
-
when /^\s*([\w\-\.\*\%\!]+)=\s*\"((\\.|[^\"])*)\"\s*,?/
|
294
|
-
key = $1
|
295
|
-
matched = $2
|
296
|
-
string = $'
|
297
|
-
ret[key] = matched.gsub(/\\(.)/, "\\1")
|
298
|
-
when /^\s*([\w\-\.\*\%\!]+)=\s*([^,\"]*),?/
|
299
|
-
key = $1
|
300
|
-
matched = $2
|
301
|
-
string = $'
|
302
|
-
ret[key] = matched.clone
|
303
|
-
when /^s*^,/
|
304
|
-
string = $'
|
305
|
-
else
|
306
|
-
break
|
307
|
-
end
|
293
|
+
string.scan(/\G\s*([\w\-.*%!]+)=\s*(?:\"((?>\\.|[^\"])*)\"|([^,\"]*))\s*,?/) do
|
294
|
+
ret[$1] = $3 || $2.gsub(/\\(.)/, "\\1")
|
308
295
|
end
|
309
296
|
ret
|
310
297
|
end
|
@@ -8,8 +8,8 @@
|
|
8
8
|
#
|
9
9
|
# $IPR: htdigest.rb,v 1.4 2003/07/22 19:20:45 gotoyuzo Exp $
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
require_relative 'userdb'
|
12
|
+
require_relative 'digestauth'
|
13
13
|
require 'tempfile'
|
14
14
|
|
15
15
|
module WEBrick
|
@@ -40,7 +40,7 @@ module WEBrick
|
|
40
40
|
@digest = Hash.new
|
41
41
|
@mutex = Thread::Mutex::new
|
42
42
|
@auth_type = DigestAuth
|
43
|
-
open(@path,"a").close unless File
|
43
|
+
File.open(@path,"a").close unless File.exist?(@path)
|
44
44
|
reload
|
45
45
|
end
|
46
46
|
|
@@ -51,7 +51,7 @@ module WEBrick
|
|
51
51
|
mtime = File::mtime(@path)
|
52
52
|
if mtime > @mtime
|
53
53
|
@digest.clear
|
54
|
-
open(@path){|io|
|
54
|
+
File.open(@path){|io|
|
55
55
|
while line = io.gets
|
56
56
|
line.chomp!
|
57
57
|
user, realm, pass = line.split(/:/, 3)
|
@@ -36,7 +36,7 @@ module WEBrick
|
|
36
36
|
@path = path
|
37
37
|
@mtime = Time.at(0)
|
38
38
|
@group = Hash.new
|
39
|
-
open(@path,"a").close unless File
|
39
|
+
File.open(@path,"a").close unless File.exist?(@path)
|
40
40
|
reload
|
41
41
|
end
|
42
42
|
|
@@ -46,7 +46,7 @@ module WEBrick
|
|
46
46
|
def reload
|
47
47
|
if (mtime = File::mtime(@path)) > @mtime
|
48
48
|
@group.clear
|
49
|
-
open(@path){|io|
|
49
|
+
File.open(@path){|io|
|
50
50
|
while line = io.gets
|
51
51
|
line.chomp!
|
52
52
|
group, members = line.split(/:\s*/)
|
@@ -63,15 +63,18 @@ module WEBrick
|
|
63
63
|
|
64
64
|
def flush(output=nil)
|
65
65
|
output ||= @path
|
66
|
-
tmp = Tempfile.
|
66
|
+
tmp = Tempfile.create("htgroup", File::dirname(output))
|
67
67
|
begin
|
68
68
|
@group.keys.sort.each{|group|
|
69
69
|
tmp.puts(format("%s: %s", group, self.members(group).join(" ")))
|
70
70
|
}
|
71
|
+
ensure
|
71
72
|
tmp.close
|
72
|
-
|
73
|
-
|
74
|
-
|
73
|
+
if $!
|
74
|
+
File.unlink(tmp.path)
|
75
|
+
else
|
76
|
+
return File.rename(tmp.path, output)
|
77
|
+
end
|
75
78
|
end
|
76
79
|
end
|
77
80
|
|
@@ -8,8 +8,8 @@
|
|
8
8
|
#
|
9
9
|
# $IPR: htpasswd.rb,v 1.4 2003/07/22 19:20:45 gotoyuzo Exp $
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
require_relative 'userdb'
|
12
|
+
require_relative 'basicauth'
|
13
13
|
require 'tempfile'
|
14
14
|
|
15
15
|
module WEBrick
|
@@ -35,12 +35,30 @@ module WEBrick
|
|
35
35
|
##
|
36
36
|
# Open a password database at +path+
|
37
37
|
|
38
|
-
def initialize(path)
|
38
|
+
def initialize(path, password_hash: nil)
|
39
39
|
@path = path
|
40
40
|
@mtime = Time.at(0)
|
41
41
|
@passwd = Hash.new
|
42
42
|
@auth_type = BasicAuth
|
43
|
-
|
43
|
+
@password_hash = password_hash
|
44
|
+
|
45
|
+
case @password_hash
|
46
|
+
when nil
|
47
|
+
# begin
|
48
|
+
# require "string/crypt"
|
49
|
+
# rescue LoadError
|
50
|
+
# warn("Unable to load string/crypt, proceeding with deprecated use of String#crypt, consider using password_hash: :bcrypt")
|
51
|
+
# end
|
52
|
+
@password_hash = :crypt
|
53
|
+
when :crypt
|
54
|
+
# require "string/crypt"
|
55
|
+
when :bcrypt
|
56
|
+
require "bcrypt"
|
57
|
+
else
|
58
|
+
raise ArgumentError, "only :crypt and :bcrypt are supported for password_hash keyword argument"
|
59
|
+
end
|
60
|
+
|
61
|
+
File.open(@path,"a").close unless File.exist?(@path)
|
44
62
|
reload
|
45
63
|
end
|
46
64
|
|
@@ -51,11 +69,19 @@ module WEBrick
|
|
51
69
|
mtime = File::mtime(@path)
|
52
70
|
if mtime > @mtime
|
53
71
|
@passwd.clear
|
54
|
-
open(@path){|io|
|
72
|
+
File.open(@path){|io|
|
55
73
|
while line = io.gets
|
56
74
|
line.chomp!
|
57
75
|
case line
|
58
76
|
when %r!\A[^:]+:[a-zA-Z0-9./]{13}\z!
|
77
|
+
if @password_hash == :bcrypt
|
78
|
+
raise StandardError, ".htpasswd file contains crypt password, only bcrypt passwords supported"
|
79
|
+
end
|
80
|
+
user, pass = line.split(":")
|
81
|
+
when %r!\A[^:]+:\$2[aby]\$\d{2}\$.{53}\z!
|
82
|
+
if @password_hash == :crypt
|
83
|
+
raise StandardError, ".htpasswd file contains bcrypt password, only crypt passwords supported"
|
84
|
+
end
|
59
85
|
user, pass = line.split(":")
|
60
86
|
when /:\$/, /:{SHA}/
|
61
87
|
raise NotImplementedError,
|
@@ -102,7 +128,14 @@ module WEBrick
|
|
102
128
|
# Sets a password in the database for +user+ in +realm+ to +pass+.
|
103
129
|
|
104
130
|
def set_passwd(realm, user, pass)
|
105
|
-
@
|
131
|
+
if @password_hash == :bcrypt
|
132
|
+
# Cost of 5 to match Apache default, and because the
|
133
|
+
# bcrypt default of 10 will introduce significant delays
|
134
|
+
# for every request.
|
135
|
+
@passwd[user] = BCrypt::Password.create(pass, :cost=>5)
|
136
|
+
else
|
137
|
+
@passwd[user] = make_passwd(realm, user, pass)
|
138
|
+
end
|
106
139
|
end
|
107
140
|
|
108
141
|
##
|
data/lib/webrick/httpproxy.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
# $IPR: httpproxy.rb,v 1.18 2003/03/08 18:58:10 gotoyuzo Exp $
|
11
11
|
# $kNotwork: straw.rb,v 1.3 2002/02/12 15:13:07 gotoken Exp $
|
12
12
|
|
13
|
-
|
13
|
+
require_relative "httpserver"
|
14
14
|
require "net/http"
|
15
15
|
|
16
16
|
module WEBrick
|
@@ -193,13 +193,13 @@ module WEBrick
|
|
193
193
|
begin
|
194
194
|
while fds = IO::select([ua, os])
|
195
195
|
if fds[0].member?(ua)
|
196
|
-
buf = ua.
|
196
|
+
buf = ua.readpartial(1024);
|
197
197
|
@logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent")
|
198
|
-
os.
|
198
|
+
os.write(buf)
|
199
199
|
elsif fds[0].member?(os)
|
200
|
-
buf = os.
|
200
|
+
buf = os.readpartial(1024);
|
201
201
|
@logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}")
|
202
|
-
ua.
|
202
|
+
ua.write(buf)
|
203
203
|
end
|
204
204
|
end
|
205
205
|
rescue
|
@@ -211,21 +211,15 @@ module WEBrick
|
|
211
211
|
end
|
212
212
|
|
213
213
|
def do_GET(req, res)
|
214
|
-
perform_proxy_request(req, res
|
215
|
-
http.get(path, header)
|
216
|
-
end
|
214
|
+
perform_proxy_request(req, res, Net::HTTP::Get)
|
217
215
|
end
|
218
216
|
|
219
217
|
def do_HEAD(req, res)
|
220
|
-
perform_proxy_request(req, res
|
221
|
-
http.head(path, header)
|
222
|
-
end
|
218
|
+
perform_proxy_request(req, res, Net::HTTP::Head)
|
223
219
|
end
|
224
220
|
|
225
221
|
def do_POST(req, res)
|
226
|
-
perform_proxy_request(req, res
|
227
|
-
http.post(path, req.body || "", header)
|
228
|
-
end
|
222
|
+
perform_proxy_request(req, res, Net::HTTP::Post, req.body_reader)
|
229
223
|
end
|
230
224
|
|
231
225
|
def do_OPTIONS(req, res)
|
@@ -301,38 +295,56 @@ module WEBrick
|
|
301
295
|
return FakeProxyURI
|
302
296
|
end
|
303
297
|
|
304
|
-
def perform_proxy_request(req, res)
|
298
|
+
def perform_proxy_request(req, res, req_class, body_stream = nil)
|
305
299
|
uri = req.request_uri
|
306
300
|
path = uri.path.dup
|
307
301
|
path << "?" << uri.query if uri.query
|
308
302
|
header = setup_proxy_header(req, res)
|
309
303
|
upstream = setup_upstream_proxy_authentication(req, res, header)
|
310
|
-
response = nil
|
311
304
|
|
305
|
+
body_tmp = []
|
312
306
|
http = Net::HTTP.new(uri.host, uri.port, upstream.host, upstream.port)
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
307
|
+
req_fib = Fiber.new do
|
308
|
+
http.start do
|
309
|
+
if @config[:ProxyTimeout]
|
310
|
+
################################## these issues are
|
311
|
+
http.open_timeout = 30 # secs # necessary (maybe because
|
312
|
+
http.read_timeout = 60 # secs # Ruby's bug, but why?)
|
313
|
+
##################################
|
314
|
+
end
|
315
|
+
if body_stream && req['transfer-encoding'] =~ /\bchunked\b/i
|
316
|
+
header['Transfer-Encoding'] = 'chunked'
|
317
|
+
end
|
318
|
+
http_req = req_class.new(path, header)
|
319
|
+
http_req.body_stream = body_stream if body_stream
|
320
|
+
http.request(http_req) do |response|
|
321
|
+
# Persistent connection requirements are mysterious for me.
|
322
|
+
# So I will close the connection in every response.
|
323
|
+
res['proxy-connection'] = "close"
|
324
|
+
res['connection'] = "close"
|
325
|
+
|
326
|
+
# stream Net::HTTP::HTTPResponse to WEBrick::HTTPResponse
|
327
|
+
res.status = response.code.to_i
|
328
|
+
res.chunked = response.chunked?
|
329
|
+
choose_header(response, res)
|
330
|
+
set_cookie(response, res)
|
331
|
+
set_via(res)
|
332
|
+
response.read_body do |buf|
|
333
|
+
body_tmp << buf
|
334
|
+
Fiber.yield # wait for res.body Proc#call
|
335
|
+
end
|
336
|
+
end # http.request
|
337
|
+
end
|
338
|
+
end
|
339
|
+
req_fib.resume # read HTTP response headers and first chunk of the body
|
340
|
+
res.body = ->(socket) do
|
341
|
+
while buf = body_tmp.shift
|
342
|
+
socket.write(buf)
|
343
|
+
buf.clear
|
344
|
+
req_fib.resume # continue response.read_body
|
319
345
|
end
|
320
|
-
response = yield(http, path, header)
|
321
346
|
end
|
322
|
-
|
323
|
-
# Persistent connection requirements are mysterious for me.
|
324
|
-
# So I will close the connection in every response.
|
325
|
-
res['proxy-connection'] = "close"
|
326
|
-
res['connection'] = "close"
|
327
|
-
|
328
|
-
# Convert Net::HTTP::HTTPResponse to WEBrick::HTTPResponse
|
329
|
-
res.status = response.code.to_i
|
330
|
-
choose_header(response, res)
|
331
|
-
set_cookie(response, res)
|
332
|
-
set_via(res)
|
333
|
-
res.body = response.body
|
334
347
|
end
|
335
|
-
|
336
348
|
# :stopdoc:
|
337
349
|
end
|
338
350
|
end
|