webricknio 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,7 @@
1
+ ---
2
+ - !IPBlockerPrefixBlock,1234/PrefixBlock
3
+ block_list:
4
+ - '999.0'
5
+ - !IPBlockerListBlock,1234/ListBlock
6
+ block_list:
7
+ - 999.0.0.1
@@ -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