webricknio 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +26 -0
- data/README.md +58 -0
- data/lib/generator/USAGE +8 -0
- data/lib/generator/webricknio.rb +57 -0
- data/lib/generator/webricknio_generator.rb +15 -0
- data/lib/rack/handler/webricknio.rb +88 -0
- data/lib/webricknio.rb +237 -0
- data/lib/webricknio/accesslog.rb +157 -0
- data/lib/webricknio/block.rb +271 -0
- data/lib/webricknio/block.yaml +7 -0
- data/lib/webricknio/config.rb +125 -0
- data/lib/webricknio/httprequest.rb +559 -0
- data/lib/webricknio/httpresponse.rb +469 -0
- data/lib/webricknio/httpserver.rb +499 -0
- data/lib/webricknio/log.rb +30 -0
- data/lib/webricknio/version.rb +14 -0
- data/webricknio.gemspec +15 -0
- metadata +79 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
#--
|
2
|
+
# accesslog.rb -- Access log handling utilities
|
3
|
+
#
|
4
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
5
|
+
# Copyright (c) 2002 keita yamaguchi
|
6
|
+
# Copyright (c) 2002 Internet Programming with Ruby writers
|
7
|
+
# Copyright (c) 2012 Pradeep Singh
|
8
|
+
#
|
9
|
+
# $IPR: accesslog.rb,v 1.1 2002/10/01 17:16:32 gotoyuzo Exp $
|
10
|
+
|
11
|
+
module WEBrickNIO
|
12
|
+
|
13
|
+
##
|
14
|
+
# AccessLog provides logging to various files in various formats.
|
15
|
+
#
|
16
|
+
# Multiple logs may be written to at the same time:
|
17
|
+
#
|
18
|
+
# access_log = [
|
19
|
+
# [$stderr, WEBrick::AccessLog::COMMON_LOG_FORMAT],
|
20
|
+
# [$stderr, WEBrick::AccessLog::REFERER_LOG_FORMAT],
|
21
|
+
# ]
|
22
|
+
#
|
23
|
+
# server = WEBrick::HTTPServer.new :AccessLog => access_log
|
24
|
+
#
|
25
|
+
# Custom log formats may be defined. WEBrick::AccessLog provides a subset
|
26
|
+
# of the formatting from Apache's mod_log_config
|
27
|
+
# http://httpd.apache.org/docs/mod/mod_log_config.html#formats. See
|
28
|
+
# AccessLog::setup_params for a list of supported options
|
29
|
+
#
|
30
|
+
# 99% copy of WEBrick::AccessLog to avoid polluting its namespace
|
31
|
+
# 1% change is in method <code>setup_params</code>
|
32
|
+
|
33
|
+
module AccessLog
|
34
|
+
|
35
|
+
##
|
36
|
+
# Raised if a parameter such as %e, %i, %o or %n is used without fetching
|
37
|
+
# a specific field.
|
38
|
+
|
39
|
+
class AccessLogError < StandardError; end
|
40
|
+
|
41
|
+
##
|
42
|
+
# The Common Log Format's time format
|
43
|
+
|
44
|
+
CLF_TIME_FORMAT = "[%d/%b/%Y:%H:%M:%S %Z]"
|
45
|
+
|
46
|
+
##
|
47
|
+
# Common Log Format
|
48
|
+
|
49
|
+
COMMON_LOG_FORMAT = "%h %l %u %t \"%r\" %s %b"
|
50
|
+
|
51
|
+
##
|
52
|
+
# Short alias for Common Log Format
|
53
|
+
|
54
|
+
CLF = COMMON_LOG_FORMAT
|
55
|
+
|
56
|
+
##
|
57
|
+
# Referer Log Format
|
58
|
+
|
59
|
+
REFERER_LOG_FORMAT = "%{Referer}i -> %U"
|
60
|
+
|
61
|
+
##
|
62
|
+
# User-Agent Log Format
|
63
|
+
|
64
|
+
AGENT_LOG_FORMAT = "%{User-Agent}i"
|
65
|
+
|
66
|
+
##
|
67
|
+
# Combined Log Format
|
68
|
+
|
69
|
+
COMBINED_LOG_FORMAT = "#{CLF} \"%{Referer}i\" \"%{User-agent}i\""
|
70
|
+
|
71
|
+
module_function
|
72
|
+
|
73
|
+
# This format specification is a subset of mod_log_config of Apache:
|
74
|
+
#
|
75
|
+
# %a:: Remote IP address
|
76
|
+
# %b:: Total response size
|
77
|
+
# %e{variable}:: Given variable in ENV
|
78
|
+
# %f:: Response filename
|
79
|
+
# %h:: Remote host name
|
80
|
+
# %{header}i:: Given request header
|
81
|
+
# %l:: Remote logname, always "-"
|
82
|
+
# %m:: Request method
|
83
|
+
# %{attr}n:: Given request attribute from <tt>req.attributes</tt>
|
84
|
+
# %{header}o:: Given response header
|
85
|
+
# %p:: Server's request port
|
86
|
+
# %{format}p:: The canonical port of the server serving the request or the
|
87
|
+
# actual port or the client's actual port. Valid formats are
|
88
|
+
# canonical, local or remote.
|
89
|
+
# %q:: Request query string
|
90
|
+
# %r:: First line of the request
|
91
|
+
# %s:: Request status
|
92
|
+
# %t:: Time the request was recieved
|
93
|
+
# %T:: Time taken to process the request
|
94
|
+
# %u:: Remote user from auth
|
95
|
+
# %U:: Unparsed URI
|
96
|
+
# %%:: Literal %
|
97
|
+
|
98
|
+
def setup_params(config, req, res)
|
99
|
+
params = Hash.new("")
|
100
|
+
#params["a"] = req.peeraddr[3]
|
101
|
+
params["a"] = req.peeraddr.get_address.get_host_address
|
102
|
+
params["b"] = res.sent_size
|
103
|
+
params["e"] = ENV
|
104
|
+
params["f"] = res.filename || ""
|
105
|
+
#params["h"] = req.peeraddr[2]
|
106
|
+
params["h"] = req.peeraddr.get_host_name
|
107
|
+
params["i"] = req
|
108
|
+
params["l"] = "-"
|
109
|
+
params["m"] = req.request_method
|
110
|
+
params["n"] = req.attributes
|
111
|
+
params["o"] = res
|
112
|
+
params["p"] = req.port
|
113
|
+
params["q"] = req.query_string
|
114
|
+
params["r"] = req.request_line.sub(/\x0d?\x0a\z/o, '')
|
115
|
+
params["s"] = res.status # won't support "%>s"
|
116
|
+
params["t"] = req.request_time
|
117
|
+
params["T"] = Time.now - req.request_time
|
118
|
+
params["u"] = req.user || "-"
|
119
|
+
params["U"] = req.unparsed_uri
|
120
|
+
params["v"] = config[:ServerName]
|
121
|
+
params
|
122
|
+
end
|
123
|
+
|
124
|
+
def format(format_string, params)
|
125
|
+
format_string.gsub(/\%(?:\{(.*?)\})?>?([a-zA-Z%])/){
|
126
|
+
param, spec = $1, $2
|
127
|
+
case spec[0]
|
128
|
+
when ?e, ?i, ?n, ?o
|
129
|
+
raise AccessLogError,
|
130
|
+
"parameter is required for \"#{spec}\"" unless param
|
131
|
+
(param = params[spec][param]) ? escape(param) : "-"
|
132
|
+
when ?t
|
133
|
+
params[spec].strftime(param || CLF_TIME_FORMAT)
|
134
|
+
when ?p
|
135
|
+
case param
|
136
|
+
when 'remote'
|
137
|
+
escape(params["i"].peeraddr[1].to_s)
|
138
|
+
else
|
139
|
+
escape(params["p"].to_s)
|
140
|
+
end
|
141
|
+
when ?%
|
142
|
+
"%"
|
143
|
+
else
|
144
|
+
escape(params[spec].to_s)
|
145
|
+
end
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
def escape(data)
|
150
|
+
if data.tainted?
|
151
|
+
data.gsub(/[[:cntrl:]\\]+/) {$&.dump[1...-1]}.untaint
|
152
|
+
else
|
153
|
+
data
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,271 @@
|
|
1
|
+
#--
|
2
|
+
# block.rb
|
3
|
+
#
|
4
|
+
# Author: Pradeep Singh
|
5
|
+
# Copyright (c) 2012 Pradeep Singh
|
6
|
+
# All rights reserved.
|
7
|
+
|
8
|
+
require 'java'
|
9
|
+
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
module WEBrickNIO
|
13
|
+
|
14
|
+
class BaseBlock
|
15
|
+
def initialize(options = {})
|
16
|
+
@logger = options["logger"] || FakeLogger.new
|
17
|
+
end
|
18
|
+
def valid?(ip)
|
19
|
+
raise "valid? Not implemented"
|
20
|
+
end
|
21
|
+
def add_ip(ip)
|
22
|
+
raise "add_ip Not implemented"
|
23
|
+
end
|
24
|
+
def block_ip?(ip)
|
25
|
+
raise "block_ip? Not implemented"
|
26
|
+
end
|
27
|
+
def self.inherited(subclass)
|
28
|
+
subclass.instance_eval {
|
29
|
+
alias old_new new
|
30
|
+
def new
|
31
|
+
alias_method :matches?, :block_ip?
|
32
|
+
old_new
|
33
|
+
end
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Wrapper that chains other blockers
|
40
|
+
#
|
41
|
+
|
42
|
+
class ChainedBlock < BaseBlock
|
43
|
+
|
44
|
+
def initialize(options = {})
|
45
|
+
begin
|
46
|
+
load
|
47
|
+
rescue Exception => ex
|
48
|
+
puts ex
|
49
|
+
create_default_chain
|
50
|
+
end
|
51
|
+
|
52
|
+
super
|
53
|
+
|
54
|
+
# at_exit do
|
55
|
+
# file = File.new(File.expand_path('block.yaml', File.dirname(__FILE__)), "w")
|
56
|
+
# dump = YAML::dump(@chain)
|
57
|
+
# file.write(dump)
|
58
|
+
# file.close
|
59
|
+
# end
|
60
|
+
end
|
61
|
+
|
62
|
+
def load
|
63
|
+
file = File.new(File.expand_path('block.yaml', File.dirname(__FILE__)), "r")
|
64
|
+
@chain = YAML::load(file)
|
65
|
+
ensure_default_chain @chain
|
66
|
+
puts @chain
|
67
|
+
end
|
68
|
+
|
69
|
+
def reload
|
70
|
+
load
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_ip(ip)
|
74
|
+
@chain.each do |blocker|
|
75
|
+
if blocker.valid? ip
|
76
|
+
blocker.add_ip ip
|
77
|
+
return true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
return false
|
81
|
+
end
|
82
|
+
|
83
|
+
def block_ip?(ip)
|
84
|
+
@chain.each do |blocker|
|
85
|
+
if blocker.block_ip?(ip)
|
86
|
+
return true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
return false
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def create_default_chain
|
95
|
+
@chain = []
|
96
|
+
add_chain_elements @chain
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_chain_elements(arr)
|
100
|
+
arr << PrefixBlock.new
|
101
|
+
arr << ListBlock.new
|
102
|
+
arr
|
103
|
+
end
|
104
|
+
|
105
|
+
def ensure_default_chain(chain)
|
106
|
+
if chain.nil? || !chain.is_a?(Array)
|
107
|
+
create_default_chain
|
108
|
+
elsif chain.length == 0
|
109
|
+
add_chain_elements chain
|
110
|
+
elsif chain.length == 1
|
111
|
+
if chain[0].class.name == "WEBrickNIO::PrefixBlock"
|
112
|
+
chain << ListBlock.new
|
113
|
+
elsif chain[0].class.name == "WEBrickNIO::ListBlock"
|
114
|
+
chain << PrefixBlock.new
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
#
|
123
|
+
# Blocks IPs with given prefix
|
124
|
+
#
|
125
|
+
|
126
|
+
class PrefixBlock < BaseBlock
|
127
|
+
|
128
|
+
def initialize(options = {})
|
129
|
+
@block_list = options["block_list"] || []
|
130
|
+
super
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.from_array(arr)
|
134
|
+
blocker = self.new
|
135
|
+
block_list = []
|
136
|
+
arr.each do |item|
|
137
|
+
blocker.add_ip item.to_s
|
138
|
+
end unless arr.nil?
|
139
|
+
blocker
|
140
|
+
end
|
141
|
+
|
142
|
+
def block_ip?(ip)
|
143
|
+
@block_list.each do |item|
|
144
|
+
if ip.start_with? item
|
145
|
+
@logger.info "ip matches: PrefixBlock - #{ip}"
|
146
|
+
return true
|
147
|
+
end
|
148
|
+
end
|
149
|
+
return false
|
150
|
+
end
|
151
|
+
|
152
|
+
def valid?(ip)
|
153
|
+
ip.split(".").size <= 3
|
154
|
+
end
|
155
|
+
|
156
|
+
def add_ip(ip)
|
157
|
+
return false if ip.nil? || ip.strip.length == 0
|
158
|
+
if valid?(ip) && !@block_list.include?(ip)
|
159
|
+
@block_list << ip
|
160
|
+
true
|
161
|
+
else
|
162
|
+
false
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def to_yaml( opts = {} )
|
167
|
+
YAML.quick_emit( nil, opts ) { |out|
|
168
|
+
out.map("!IPBlockerPrefixBlock,1234/PrefixBlock" ) { |map|
|
169
|
+
map.add("block_list", @block_list)
|
170
|
+
}
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
def to_s
|
175
|
+
"PrefixBlock<#{object_id}>:#{@block_list}"
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
#
|
182
|
+
# Blocks IPs that are exact match
|
183
|
+
#
|
184
|
+
|
185
|
+
class ListBlock < BaseBlock
|
186
|
+
|
187
|
+
def initialize(options = {})
|
188
|
+
@block_list = options["block_list"] || java.util.concurrent.ConcurrentSkipListSet.new
|
189
|
+
super
|
190
|
+
end
|
191
|
+
|
192
|
+
def self.from_array(arr)
|
193
|
+
blocker = self.new
|
194
|
+
arr.each do |item|
|
195
|
+
blocker.add_ip item.to_s
|
196
|
+
end unless arr.nil?
|
197
|
+
blocker
|
198
|
+
end
|
199
|
+
|
200
|
+
def block_ip?(ip)
|
201
|
+
if @block_list.include? ip
|
202
|
+
@logger.info "ip matches: ListBlock - #{ip}"
|
203
|
+
true
|
204
|
+
else
|
205
|
+
false
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def valid?(ip)
|
210
|
+
ip.split(".").size > 3
|
211
|
+
end
|
212
|
+
|
213
|
+
def add_ip(ip)
|
214
|
+
return false if ip.nil? || ip.strip.length == 0
|
215
|
+
if valid? ip
|
216
|
+
@block_list.add ip
|
217
|
+
true
|
218
|
+
else
|
219
|
+
false
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def to_yaml( opts = {} )
|
224
|
+
YAML.quick_emit( nil, opts ) { |out|
|
225
|
+
out.map("!IPBlockerListBlock,1234/ListBlock" ) { |map|
|
226
|
+
map.add("block_list", @block_list.to_a)
|
227
|
+
}
|
228
|
+
}
|
229
|
+
end
|
230
|
+
|
231
|
+
def to_s
|
232
|
+
"ListBlock<#{object_id}>:#{@block_list.to_a}"
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
|
239
|
+
YAML::add_domain_type("IPBlockerListBlock,1234", "ListBlock") do |type, val|
|
240
|
+
ListBlock.from_array(val["block_list"])
|
241
|
+
end
|
242
|
+
|
243
|
+
YAML::add_domain_type("IPBlockerPrefixBlock,1234", "PrefixBlock") do |type, val|
|
244
|
+
PrefixBlock.from_array(val["block_list"])
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
|
249
|
+
class FakeLogger
|
250
|
+
def method_missing(method, *args, &block)
|
251
|
+
puts args
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
#chain = WEBrickNIO::ChainedBlock.new
|
258
|
+
|
259
|
+
#ip ="180.76"
|
260
|
+
#chain.add(ip)
|
261
|
+
|
262
|
+
#ip ="92.240.68.152"
|
263
|
+
#chain.add(ip)
|
264
|
+
#ip ="180.76"
|
265
|
+
#chain.block_ip? ip
|
266
|
+
|
267
|
+
#ip ="92.240.68.152"
|
268
|
+
#chain.matches? ip
|
269
|
+
|
270
|
+
|
271
|
+
|
@@ -0,0 +1,125 @@
|
|
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 'webricknio/version'
|
12
|
+
require 'webrick/httpversion'
|
13
|
+
require 'webrick/httputils'
|
14
|
+
require 'webrick/utils'
|
15
|
+
require 'webrick/log'
|
16
|
+
require 'webricknio/log'
|
17
|
+
|
18
|
+
module WEBrickNIO
|
19
|
+
module Config
|
20
|
+
LIBDIR = File::dirname(__FILE__)
|
21
|
+
|
22
|
+
# for GenericServer
|
23
|
+
General = {
|
24
|
+
:ServerName => ::WEBrick::Utils::getservername,
|
25
|
+
:BindAddress => nil, # "0.0.0.0" or "::" or nil
|
26
|
+
:Port => nil, # users MUST specify this!!
|
27
|
+
:ServerType => nil, # default: WEBrick::SimpleServer
|
28
|
+
:Logger => nil, # default: WEBrick::Log.new
|
29
|
+
#:ServerSoftware => "WEBrickNIO/#{WEBrickNIO::VERSION} " +
|
30
|
+
# "(Ruby/#{RUBY_VERSION}/#{RUBY_RELEASE_DATE})",
|
31
|
+
:ServerSoftware => "pks/#{WEBrickNIO::VERSION} ",
|
32
|
+
:TempDir => ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'/tmp',
|
33
|
+
:DoNotListen => false,
|
34
|
+
:StartCallback => nil,
|
35
|
+
:StopCallback => nil,
|
36
|
+
:AcceptCallback => nil,
|
37
|
+
:DoNotReverseLookup => nil,
|
38
|
+
:ShutdownSocketWithoutClose => false,
|
39
|
+
}
|
40
|
+
|
41
|
+
# for HTTPServer, HTTPRequest, HTTPResponse ...
|
42
|
+
HTTP = General.dup.update(
|
43
|
+
:Port => 80,
|
44
|
+
:RequestTimeout => 5,
|
45
|
+
:NumThreads => 20,
|
46
|
+
:HTTPVersion => ::WEBrick::HTTPVersion.new("1.1"),
|
47
|
+
:AccessLog => nil,
|
48
|
+
:LogLocation => nil, #"log/webrick.log"
|
49
|
+
:LogLevel => ::WEBrick::Log::DEBUG,
|
50
|
+
:MimeTypes => ::WEBrick::HTTPUtils::DefaultMimeTypes,
|
51
|
+
:DirectoryIndex => ["index.html","index.htm","index.cgi","index.rhtml"],
|
52
|
+
:DocumentRoot => nil,
|
53
|
+
:DocumentRootOptions => { :FancyIndexing => true },
|
54
|
+
:RequestCallback => nil,
|
55
|
+
:ServerAlias => nil,
|
56
|
+
:InputBufferSize => 65536, # input buffer size in reading request body
|
57
|
+
:OutputBufferSize => 65536, # output buffer size in sending File or IO
|
58
|
+
|
59
|
+
# for HTTPProxyServer
|
60
|
+
:ProxyAuthProc => nil,
|
61
|
+
:ProxyContentHandler => nil,
|
62
|
+
:ProxyVia => true,
|
63
|
+
:ProxyTimeout => true,
|
64
|
+
:ProxyURI => nil,
|
65
|
+
|
66
|
+
:CGIInterpreter => nil,
|
67
|
+
:CGIPathEnv => nil,
|
68
|
+
|
69
|
+
# workaround: if Request-URIs contain 8bit chars,
|
70
|
+
# they should be escaped before calling of URI::parse().
|
71
|
+
:Escape8bitURI => false
|
72
|
+
)
|
73
|
+
|
74
|
+
FileHandler = {
|
75
|
+
:NondisclosureName => [".ht*", "*~"],
|
76
|
+
:FancyIndexing => false,
|
77
|
+
:HandlerTable => {},
|
78
|
+
:HandlerCallback => nil,
|
79
|
+
:DirectoryCallback => nil,
|
80
|
+
:FileCallback => nil,
|
81
|
+
:UserDir => nil, # e.g. "public_html"
|
82
|
+
:AcceptableLanguages => [] # ["en", "ja", ... ]
|
83
|
+
}
|
84
|
+
|
85
|
+
BasicAuth = {
|
86
|
+
:AutoReloadUserDB => true,
|
87
|
+
}
|
88
|
+
|
89
|
+
##
|
90
|
+
# Default configuration for WEBrick::HTTPAuth::DigestAuth.
|
91
|
+
#
|
92
|
+
# :Algorithm:: MD5, MD5-sess (default), SHA1, SHA1-sess
|
93
|
+
# :Domain:: An Array of URIs that define the protected space
|
94
|
+
# :Qop:: 'auth' for authentication, 'auth-int' for integrity protection or
|
95
|
+
# both
|
96
|
+
# :UseOpaque:: Should the server send opaque values to the client? This
|
97
|
+
# helps prevent replay attacks.
|
98
|
+
# :CheckNc:: Should the server check the nonce count? This helps the
|
99
|
+
# server detect replay attacks.
|
100
|
+
# :UseAuthenticationInfoHeader:: Should the server send an
|
101
|
+
# AuthenticationInfo header?
|
102
|
+
# :AutoReloadUserDB:: Reload the user database provided by :UserDB
|
103
|
+
# automatically?
|
104
|
+
# :NonceExpirePeriod:: How long should we store used nonces? Default is
|
105
|
+
# 30 minutes.
|
106
|
+
# :NonceExpireDelta:: How long is a nonce valid? Default is 1 minute
|
107
|
+
# :InternetExplorerHack:: Hack which allows Internet Explorer to work.
|
108
|
+
# :OperaHack:: Hack which allows Opera to work.
|
109
|
+
|
110
|
+
DigestAuth = {
|
111
|
+
:Algorithm => 'MD5-sess', # or 'MD5'
|
112
|
+
:Domain => nil, # an array includes domain names.
|
113
|
+
:Qop => [ 'auth' ], # 'auth' or 'auth-int' or both.
|
114
|
+
:UseOpaque => true,
|
115
|
+
:UseNextNonce => false,
|
116
|
+
:CheckNc => false,
|
117
|
+
:UseAuthenticationInfoHeader => true,
|
118
|
+
:AutoReloadUserDB => true,
|
119
|
+
:NonceExpirePeriod => 30*60,
|
120
|
+
:NonceExpireDelta => 60,
|
121
|
+
:InternetExplorerHack => true,
|
122
|
+
:OperaHack => true,
|
123
|
+
}
|
124
|
+
end
|
125
|
+
end
|