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.
- data/README.txt +21 -0
- data/lib/webrick.rb +227 -0
- data/lib/webrick/accesslog.rb +151 -0
- data/lib/webrick/cgi.rb +260 -0
- data/lib/webrick/compat.rb +35 -0
- data/lib/webrick/config.rb +121 -0
- data/lib/webrick/cookie.rb +110 -0
- data/lib/webrick/htmlutils.rb +28 -0
- data/lib/webrick/httpauth.rb +95 -0
- data/lib/webrick/httpauth/authenticator.rb +112 -0
- data/lib/webrick/httpauth/basicauth.rb +108 -0
- data/lib/webrick/httpauth/digestauth.rb +392 -0
- data/lib/webrick/httpauth/htdigest.rb +128 -0
- data/lib/webrick/httpauth/htgroup.rb +93 -0
- data/lib/webrick/httpauth/htpasswd.rb +121 -0
- data/lib/webrick/httpauth/userdb.rb +52 -0
- data/lib/webrick/httpproxy.rb +305 -0
- data/lib/webrick/httprequest.rb +461 -0
- data/lib/webrick/httpresponse.rb +399 -0
- data/lib/webrick/https.rb +64 -0
- data/lib/webrick/httpserver.rb +264 -0
- data/lib/webrick/httpservlet.rb +22 -0
- data/lib/webrick/httpservlet/abstract.rb +153 -0
- data/lib/webrick/httpservlet/cgi_runner.rb +46 -0
- data/lib/webrick/httpservlet/cgihandler.rb +108 -0
- data/lib/webrick/httpservlet/erbhandler.rb +87 -0
- data/lib/webrick/httpservlet/filehandler.rb +470 -0
- data/lib/webrick/httpservlet/prochandler.rb +33 -0
- data/lib/webrick/httpstatus.rb +184 -0
- data/lib/webrick/httputils.rb +394 -0
- data/lib/webrick/httpversion.rb +49 -0
- data/lib/webrick/log.rb +136 -0
- data/lib/webrick/server.rb +218 -0
- data/lib/webrick/ssl.rb +127 -0
- data/lib/webrick/utils.rb +241 -0
- data/lib/webrick/version.rb +13 -0
- data/sample/webrick/demo-app.rb +66 -0
- data/sample/webrick/demo-multipart.cgi +12 -0
- data/sample/webrick/demo-servlet.rb +6 -0
- data/sample/webrick/demo-urlencoded.cgi +12 -0
- data/sample/webrick/hello.cgi +11 -0
- data/sample/webrick/hello.rb +8 -0
- data/sample/webrick/httpd.rb +23 -0
- data/sample/webrick/httpproxy.rb +25 -0
- data/sample/webrick/httpsd.rb +33 -0
- data/test/openssl/utils.rb +313 -0
- data/test/ruby/envutil.rb +208 -0
- data/test/webrick/test_cgi.rb +134 -0
- data/test/webrick/test_cookie.rb +131 -0
- data/test/webrick/test_filehandler.rb +285 -0
- data/test/webrick/test_httpauth.rb +167 -0
- data/test/webrick/test_httpproxy.rb +282 -0
- data/test/webrick/test_httprequest.rb +411 -0
- data/test/webrick/test_httpresponse.rb +49 -0
- data/test/webrick/test_httpserver.rb +305 -0
- data/test/webrick/test_httputils.rb +96 -0
- data/test/webrick/test_httpversion.rb +40 -0
- data/test/webrick/test_server.rb +67 -0
- data/test/webrick/test_utils.rb +64 -0
- data/test/webrick/utils.rb +58 -0
- data/test/webrick/webrick.cgi +36 -0
- data/test/webrick/webrick_long_filename.cgi +36 -0
- metadata +106 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# compat.rb -- cross platform compatibility
|
3
|
+
#
|
4
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
5
|
+
# Copyright (c) 2002 GOTOU Yuuzou
|
6
|
+
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
|
7
|
+
# reserved.
|
8
|
+
#
|
9
|
+
# $IPR: compat.rb,v 1.6 2002/10/01 17:16:32 gotoyuzo Exp $
|
10
|
+
|
11
|
+
##
|
12
|
+
# System call error module used by webrick for cross platform compatability.
|
13
|
+
#
|
14
|
+
# EPROTO:: protocol error
|
15
|
+
# ECONNRESET:: remote host reset the connection request
|
16
|
+
# ECONNABORTED:: Client sent TCP reset (RST) before server has accepted the
|
17
|
+
# connection requested by client.
|
18
|
+
#
|
19
|
+
module Errno
|
20
|
+
##
|
21
|
+
# Protocol error.
|
22
|
+
|
23
|
+
class EPROTO < SystemCallError; end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Remote host reset the connection request.
|
27
|
+
|
28
|
+
class ECONNRESET < SystemCallError; end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Client sent TCP reset (RST) before server has accepted the connection
|
32
|
+
# requested by client.
|
33
|
+
|
34
|
+
class ECONNABORTED < SystemCallError; end
|
35
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
#
|
2
|
+
# config.rb -- Default configurations.
|
3
|
+
#
|
4
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
5
|
+
# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
|
6
|
+
# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
|
7
|
+
# reserved.
|
8
|
+
#
|
9
|
+
# $IPR: config.rb,v 1.52 2003/07/22 19:20:42 gotoyuzo Exp $
|
10
|
+
|
11
|
+
require 'webrick/version'
|
12
|
+
require 'webrick/httpversion'
|
13
|
+
require 'webrick/httputils'
|
14
|
+
require 'webrick/utils'
|
15
|
+
require 'webrick/log'
|
16
|
+
|
17
|
+
module WEBrick
|
18
|
+
module Config
|
19
|
+
LIBDIR = File::dirname(__FILE__)
|
20
|
+
|
21
|
+
# for GenericServer
|
22
|
+
General = {
|
23
|
+
:ServerName => Utils::getservername,
|
24
|
+
:BindAddress => nil, # "0.0.0.0" or "::" or nil
|
25
|
+
:Port => nil, # users MUST specify this!!
|
26
|
+
:MaxClients => 100, # maximum number of the concurrent connections
|
27
|
+
:ServerType => nil, # default: WEBrick::SimpleServer
|
28
|
+
:Logger => nil, # default: WEBrick::Log.new
|
29
|
+
:ServerSoftware => "WEBrick/#{WEBrick::VERSION} " +
|
30
|
+
"(Ruby/#{RUBY_VERSION}/#{RUBY_RELEASE_DATE})",
|
31
|
+
:TempDir => ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'/tmp',
|
32
|
+
:DoNotListen => false,
|
33
|
+
:StartCallback => nil,
|
34
|
+
:StopCallback => nil,
|
35
|
+
:AcceptCallback => nil,
|
36
|
+
:DoNotReverseLookup => nil,
|
37
|
+
:ShutdownSocketWithoutClose => false,
|
38
|
+
}
|
39
|
+
|
40
|
+
# for HTTPServer, HTTPRequest, HTTPResponse ...
|
41
|
+
HTTP = General.dup.update(
|
42
|
+
:Port => 80,
|
43
|
+
:RequestTimeout => 30,
|
44
|
+
:HTTPVersion => HTTPVersion.new("1.1"),
|
45
|
+
:AccessLog => nil,
|
46
|
+
:MimeTypes => HTTPUtils::DefaultMimeTypes,
|
47
|
+
:DirectoryIndex => ["index.html","index.htm","index.cgi","index.rhtml"],
|
48
|
+
:DocumentRoot => nil,
|
49
|
+
:DocumentRootOptions => { :FancyIndexing => true },
|
50
|
+
:RequestCallback => nil,
|
51
|
+
:ServerAlias => nil,
|
52
|
+
:InputBufferSize => 65536, # input buffer size in reading request body
|
53
|
+
:OutputBufferSize => 65536, # output buffer size in sending File or IO
|
54
|
+
|
55
|
+
# for HTTPProxyServer
|
56
|
+
:ProxyAuthProc => nil,
|
57
|
+
:ProxyContentHandler => nil,
|
58
|
+
:ProxyVia => true,
|
59
|
+
:ProxyTimeout => true,
|
60
|
+
:ProxyURI => nil,
|
61
|
+
|
62
|
+
:CGIInterpreter => nil,
|
63
|
+
:CGIPathEnv => nil,
|
64
|
+
|
65
|
+
# workaround: if Request-URIs contain 8bit chars,
|
66
|
+
# they should be escaped before calling of URI::parse().
|
67
|
+
:Escape8bitURI => false
|
68
|
+
)
|
69
|
+
|
70
|
+
FileHandler = {
|
71
|
+
:NondisclosureName => [".ht*", "*~"],
|
72
|
+
:FancyIndexing => false,
|
73
|
+
:HandlerTable => {},
|
74
|
+
:HandlerCallback => nil,
|
75
|
+
:DirectoryCallback => nil,
|
76
|
+
:FileCallback => nil,
|
77
|
+
:UserDir => nil, # e.g. "public_html"
|
78
|
+
:AcceptableLanguages => [] # ["en", "ja", ... ]
|
79
|
+
}
|
80
|
+
|
81
|
+
BasicAuth = {
|
82
|
+
:AutoReloadUserDB => true,
|
83
|
+
}
|
84
|
+
|
85
|
+
##
|
86
|
+
# Default configuration for WEBrick::HTTPAuth::DigestAuth.
|
87
|
+
#
|
88
|
+
# :Algorithm:: MD5, MD5-sess (default), SHA1, SHA1-sess
|
89
|
+
# :Domain:: An Array of URIs that define the protected space
|
90
|
+
# :Qop:: 'auth' for authentication, 'auth-int' for integrity protection or
|
91
|
+
# both
|
92
|
+
# :UseOpaque:: Should the server send opaque values to the client? This
|
93
|
+
# helps prevent replay attacks.
|
94
|
+
# :CheckNc:: Should the server check the nonce count? This helps the
|
95
|
+
# server detect replay attacks.
|
96
|
+
# :UseAuthenticationInfoHeader:: Should the server send an
|
97
|
+
# AuthenticationInfo header?
|
98
|
+
# :AutoReloadUserDB:: Reload the user database provided by :UserDB
|
99
|
+
# automatically?
|
100
|
+
# :NonceExpirePeriod:: How long should we store used nonces? Default is
|
101
|
+
# 30 minutes.
|
102
|
+
# :NonceExpireDelta:: How long is a nonce valid? Default is 1 minute
|
103
|
+
# :InternetExplorerHack:: Hack which allows Internet Explorer to work.
|
104
|
+
# :OperaHack:: Hack which allows Opera to work.
|
105
|
+
|
106
|
+
DigestAuth = {
|
107
|
+
:Algorithm => 'MD5-sess', # or 'MD5'
|
108
|
+
:Domain => nil, # an array includes domain names.
|
109
|
+
:Qop => [ 'auth' ], # 'auth' or 'auth-int' or both.
|
110
|
+
:UseOpaque => true,
|
111
|
+
:UseNextNonce => false,
|
112
|
+
:CheckNc => false,
|
113
|
+
:UseAuthenticationInfoHeader => true,
|
114
|
+
:AutoReloadUserDB => true,
|
115
|
+
:NonceExpirePeriod => 30*60,
|
116
|
+
:NonceExpireDelta => 60,
|
117
|
+
:InternetExplorerHack => true,
|
118
|
+
:OperaHack => true,
|
119
|
+
}
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
#
|
2
|
+
# cookie.rb -- Cookie class
|
3
|
+
#
|
4
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
5
|
+
# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
|
6
|
+
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
|
7
|
+
# reserved.
|
8
|
+
#
|
9
|
+
# $IPR: cookie.rb,v 1.16 2002/09/21 12:23:35 gotoyuzo Exp $
|
10
|
+
|
11
|
+
require 'time'
|
12
|
+
require 'webrick/httputils'
|
13
|
+
|
14
|
+
module WEBrick
|
15
|
+
class Cookie
|
16
|
+
|
17
|
+
attr_reader :name
|
18
|
+
attr_accessor :value, :version
|
19
|
+
attr_accessor :domain, :path, :secure
|
20
|
+
attr_accessor :comment, :max_age
|
21
|
+
#attr_accessor :comment_url, :discard, :port
|
22
|
+
|
23
|
+
def initialize(name, value)
|
24
|
+
@name = name
|
25
|
+
@value = value
|
26
|
+
@version = 0 # Netscape Cookie
|
27
|
+
|
28
|
+
@domain = @path = @secure = @comment = @max_age =
|
29
|
+
@expires = @comment_url = @discard = @port = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def expires=(t)
|
33
|
+
@expires = t && (t.is_a?(Time) ? t.httpdate : t.to_s)
|
34
|
+
end
|
35
|
+
|
36
|
+
def expires
|
37
|
+
@expires && Time.parse(@expires)
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
ret = ""
|
42
|
+
ret << @name << "=" << @value
|
43
|
+
ret << "; " << "Version=" << @version.to_s if @version > 0
|
44
|
+
ret << "; " << "Domain=" << @domain if @domain
|
45
|
+
ret << "; " << "Expires=" << @expires if @expires
|
46
|
+
ret << "; " << "Max-Age=" << @max_age.to_s if @max_age
|
47
|
+
ret << "; " << "Comment=" << @comment if @comment
|
48
|
+
ret << "; " << "Path=" << @path if @path
|
49
|
+
ret << "; " << "Secure" if @secure
|
50
|
+
ret
|
51
|
+
end
|
52
|
+
|
53
|
+
# Cookie::parse()
|
54
|
+
# It parses Cookie field sent from the user agent.
|
55
|
+
def self.parse(str)
|
56
|
+
if str
|
57
|
+
ret = []
|
58
|
+
cookie = nil
|
59
|
+
ver = 0
|
60
|
+
str.split(/[;,]\s+/).each{|x|
|
61
|
+
key, val = x.split(/=/,2)
|
62
|
+
val = val ? HTTPUtils::dequote(val) : ""
|
63
|
+
case key
|
64
|
+
when "$Version"; ver = val.to_i
|
65
|
+
when "$Path"; cookie.path = val
|
66
|
+
when "$Domain"; cookie.domain = val
|
67
|
+
when "$Port"; cookie.port = val
|
68
|
+
else
|
69
|
+
ret << cookie if cookie
|
70
|
+
cookie = self.new(key, val)
|
71
|
+
cookie.version = ver
|
72
|
+
end
|
73
|
+
}
|
74
|
+
ret << cookie if cookie
|
75
|
+
ret
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.parse_set_cookie(str)
|
80
|
+
cookie_elem = str.split(/;/)
|
81
|
+
first_elem = cookie_elem.shift
|
82
|
+
first_elem.strip!
|
83
|
+
key, value = first_elem.split(/=/, 2)
|
84
|
+
cookie = new(key, HTTPUtils.dequote(value))
|
85
|
+
cookie_elem.each{|pair|
|
86
|
+
pair.strip!
|
87
|
+
key, value = pair.split(/=/, 2)
|
88
|
+
if value
|
89
|
+
value = HTTPUtils.dequote(value.strip)
|
90
|
+
end
|
91
|
+
case key.downcase
|
92
|
+
when "domain" then cookie.domain = value
|
93
|
+
when "path" then cookie.path = value
|
94
|
+
when "expires" then cookie.expires = value
|
95
|
+
when "max-age" then cookie.max_age = Integer(value)
|
96
|
+
when "comment" then cookie.comment = value
|
97
|
+
when "version" then cookie.version = Integer(value)
|
98
|
+
when "secure" then cookie.secure = true
|
99
|
+
end
|
100
|
+
}
|
101
|
+
return cookie
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.parse_set_cookies(str)
|
105
|
+
return str.split(/,(?=[^;,]*=)|,$/).collect{|c|
|
106
|
+
parse_set_cookie(c)
|
107
|
+
}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#--
|
2
|
+
# htmlutils.rb -- HTMLUtils Module
|
3
|
+
#
|
4
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
5
|
+
# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
|
6
|
+
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
|
7
|
+
# reserved.
|
8
|
+
#
|
9
|
+
# $IPR: htmlutils.rb,v 1.7 2002/09/21 12:23:35 gotoyuzo Exp $
|
10
|
+
|
11
|
+
module WEBrick
|
12
|
+
module HTMLUtils
|
13
|
+
|
14
|
+
##
|
15
|
+
# Escapes &, ", > and < in +string+
|
16
|
+
|
17
|
+
def escape(string)
|
18
|
+
str = string ? string.dup : ""
|
19
|
+
str.gsub!(/&/n, '&')
|
20
|
+
str.gsub!(/\"/n, '"')
|
21
|
+
str.gsub!(/>/n, '>')
|
22
|
+
str.gsub!(/</n, '<')
|
23
|
+
str
|
24
|
+
end
|
25
|
+
module_function :escape
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
#
|
2
|
+
# httpauth.rb -- HTTP access authentication
|
3
|
+
#
|
4
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
5
|
+
# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
|
6
|
+
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
|
7
|
+
# reserved.
|
8
|
+
#
|
9
|
+
# $IPR: httpauth.rb,v 1.14 2003/07/22 19:20:42 gotoyuzo Exp $
|
10
|
+
|
11
|
+
require 'webrick/httpauth/basicauth'
|
12
|
+
require 'webrick/httpauth/digestauth'
|
13
|
+
require 'webrick/httpauth/htpasswd'
|
14
|
+
require 'webrick/httpauth/htdigest'
|
15
|
+
require 'webrick/httpauth/htgroup'
|
16
|
+
|
17
|
+
module WEBrick
|
18
|
+
|
19
|
+
##
|
20
|
+
# HTTPAuth provides both basic and digest authentication.
|
21
|
+
#
|
22
|
+
# To enable authentication for requests in WEBrick you will need a user
|
23
|
+
# database and an authenticator. To start, here's an Htpasswd database for
|
24
|
+
# use with a DigestAuth authenticator:
|
25
|
+
#
|
26
|
+
# config = { :Realm => 'DigestAuth example realm' }
|
27
|
+
#
|
28
|
+
# htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file'
|
29
|
+
# htpasswd.auth_type = WEBrick::HTTPAuth::DigestAuth
|
30
|
+
# htpasswd.set_passwd config[:Realm], 'username', 'password'
|
31
|
+
# htpasswd.flush
|
32
|
+
#
|
33
|
+
# The +:Realm+ is used to provide different access to different groups
|
34
|
+
# across several resources on a server. Typically you'll need only one
|
35
|
+
# realm for a server.
|
36
|
+
#
|
37
|
+
# This database can be used to create an authenticator:
|
38
|
+
#
|
39
|
+
# config[:UserDB] = htpasswd
|
40
|
+
#
|
41
|
+
# digest_auth = WEBrick::HTTPAuth::DigestAuth.new config
|
42
|
+
#
|
43
|
+
# To authenticate a request call #authenticate with a request and response
|
44
|
+
# object in a servlet:
|
45
|
+
#
|
46
|
+
# def do_GET req, res
|
47
|
+
# @authenticator.authenticate req, res
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# For digest authentication the authenticator must not be created every
|
51
|
+
# request, it must be passed in as an option via WEBrick::HTTPServer#mount.
|
52
|
+
|
53
|
+
module HTTPAuth
|
54
|
+
module_function
|
55
|
+
|
56
|
+
def _basic_auth(req, res, realm, req_field, res_field, err_type,
|
57
|
+
block) # :nodoc:
|
58
|
+
user = pass = nil
|
59
|
+
if /^Basic\s+(.*)/o =~ req[req_field]
|
60
|
+
userpass = $1
|
61
|
+
user, pass = userpass.unpack("m*")[0].split(":", 2)
|
62
|
+
end
|
63
|
+
if block.call(user, pass)
|
64
|
+
req.user = user
|
65
|
+
return
|
66
|
+
end
|
67
|
+
res[res_field] = "Basic realm=\"#{realm}\""
|
68
|
+
raise err_type
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Simple wrapper for providing basic authentication for a request. When
|
73
|
+
# called with a request +req+, response +res+, authentication +realm+ and
|
74
|
+
# +block+ the block will be called with a +username+ and +password+. If
|
75
|
+
# the block returns true the request is allowed to continue, otherwise an
|
76
|
+
# HTTPStatus::Unauthorized error is raised.
|
77
|
+
|
78
|
+
def basic_auth(req, res, realm, &block) # :yield: username, password
|
79
|
+
_basic_auth(req, res, realm, "Authorization", "WWW-Authenticate",
|
80
|
+
HTTPStatus::Unauthorized, block)
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Simple wrapper for providing basic authentication for a proxied request.
|
85
|
+
# When called with a request +req+, response +res+, authentication +realm+
|
86
|
+
# and +block+ the block will be called with a +username+ and +password+.
|
87
|
+
# If the block returns true the request is allowed to continue, otherwise
|
88
|
+
# an HTTPStatus::ProxyAuthenticationRequired error is raised.
|
89
|
+
|
90
|
+
def proxy_basic_auth(req, res, realm, &block) # :yield: username, password
|
91
|
+
_basic_auth(req, res, realm, "Proxy-Authorization", "Proxy-Authenticate",
|
92
|
+
HTTPStatus::ProxyAuthenticationRequired, block)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
#--
|
2
|
+
# httpauth/authenticator.rb -- Authenticator mix-in module.
|
3
|
+
#
|
4
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
5
|
+
# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
|
6
|
+
# reserved.
|
7
|
+
#
|
8
|
+
# $IPR: authenticator.rb,v 1.3 2003/02/20 07:15:47 gotoyuzo Exp $
|
9
|
+
|
10
|
+
module WEBrick
|
11
|
+
module HTTPAuth
|
12
|
+
|
13
|
+
##
|
14
|
+
# Module providing generic support for both Digest and Basic
|
15
|
+
# authentication schemes.
|
16
|
+
|
17
|
+
module Authenticator
|
18
|
+
|
19
|
+
RequestField = "Authorization"
|
20
|
+
ResponseField = "WWW-Authenticate"
|
21
|
+
ResponseInfoField = "Authentication-Info"
|
22
|
+
AuthException = HTTPStatus::Unauthorized
|
23
|
+
|
24
|
+
##
|
25
|
+
# Method of authentication, must be overridden by the including class
|
26
|
+
|
27
|
+
AuthScheme = nil
|
28
|
+
|
29
|
+
##
|
30
|
+
# The realm this authenticator covers
|
31
|
+
|
32
|
+
attr_reader :realm
|
33
|
+
|
34
|
+
##
|
35
|
+
# The user database for this authenticator
|
36
|
+
|
37
|
+
attr_reader :userdb
|
38
|
+
|
39
|
+
##
|
40
|
+
# The logger for this authenticator
|
41
|
+
|
42
|
+
attr_reader :logger
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
##
|
47
|
+
# Initializes the authenticator from +config+
|
48
|
+
|
49
|
+
def check_init(config)
|
50
|
+
[:UserDB, :Realm].each{|sym|
|
51
|
+
unless config[sym]
|
52
|
+
raise ArgumentError, "Argument #{sym.inspect} missing."
|
53
|
+
end
|
54
|
+
}
|
55
|
+
@realm = config[:Realm]
|
56
|
+
@userdb = config[:UserDB]
|
57
|
+
@logger = config[:Logger] || Log::new($stderr)
|
58
|
+
@reload_db = config[:AutoReloadUserDB]
|
59
|
+
@request_field = self::class::RequestField
|
60
|
+
@response_field = self::class::ResponseField
|
61
|
+
@resp_info_field = self::class::ResponseInfoField
|
62
|
+
@auth_exception = self::class::AuthException
|
63
|
+
@auth_scheme = self::class::AuthScheme
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Ensures +req+ has credentials that can be authenticated.
|
68
|
+
|
69
|
+
def check_scheme(req)
|
70
|
+
unless credentials = req[@request_field]
|
71
|
+
error("no credentials in the request.")
|
72
|
+
return nil
|
73
|
+
end
|
74
|
+
unless match = /^#{@auth_scheme}\s+/i.match(credentials)
|
75
|
+
error("invalid scheme in %s.", credentials)
|
76
|
+
info("%s: %s", @request_field, credentials) if $DEBUG
|
77
|
+
return nil
|
78
|
+
end
|
79
|
+
return match.post_match
|
80
|
+
end
|
81
|
+
|
82
|
+
def log(meth, fmt, *args)
|
83
|
+
msg = format("%s %s: ", @auth_scheme, @realm)
|
84
|
+
msg << fmt % args
|
85
|
+
@logger.send(meth, msg)
|
86
|
+
end
|
87
|
+
|
88
|
+
def error(fmt, *args)
|
89
|
+
if @logger.error?
|
90
|
+
log(:error, fmt, *args)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def info(fmt, *args)
|
95
|
+
if @logger.info?
|
96
|
+
log(:info, fmt, *args)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Module providing generic support for both Digest and Basic
|
103
|
+
# authentication schemes for proxies.
|
104
|
+
|
105
|
+
module ProxyAuthenticator
|
106
|
+
RequestField = "Proxy-Authorization"
|
107
|
+
ResponseField = "Proxy-Authenticate"
|
108
|
+
InfoField = "Proxy-Authentication-Info"
|
109
|
+
AuthException = HTTPStatus::ProxyAuthenticationRequired
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|