1
0
Fork 0
mirror of https://github.com/sinatra/sinatra synced 2023-03-27 23:18:01 -04:00
sinatra/rack-protection/lib/rack/protection/base.rb

102 lines
2.5 KiB
Ruby
Raw Normal View History

2011-05-23 04:07:54 -04:00
require 'rack/protection'
2011-05-29 07:01:47 -04:00
require 'digest'
2011-05-25 06:27:18 -04:00
require 'logger'
require 'uri'
2011-05-23 04:07:54 -04:00
module Rack
module Protection
class Base
2011-05-25 06:27:18 -04:00
DEFAULT_OPTIONS = {
2011-05-29 07:01:47 -04:00
:reaction => :default_reaction, :logging => true,
:message => 'Forbidden', :encryptor => Digest::SHA1,
:session_key => 'rack.session', :status => 403,
:allow_empty_referrer => true
2011-05-25 06:27:18 -04:00
}
2011-05-23 04:07:54 -04:00
attr_reader :app, :options
def self.default_options(options)
define_method(:default_options) { super().merge(options) }
end
2011-05-25 06:27:18 -04:00
def self.default_reaction(reaction)
alias_method(:default_reaction, reaction)
end
2011-05-23 04:07:54 -04:00
def default_options
DEFAULT_OPTIONS
end
def initialize(app, options = {})
@app, @options = app, default_options.merge(options)
2011-05-23 04:07:54 -04:00
end
2011-05-25 06:27:18 -04:00
def safe?(env)
%w[GET HEAD OPTIONS TRACE].include? env['REQUEST_METHOD']
end
2011-05-23 04:07:54 -04:00
def accepts?(env)
raise NotImplementedError, "#{self.class} implementation pending"
end
def call(env)
unless accepts? env
2011-05-25 06:27:18 -04:00
warn env, "attack prevented by #{self.class}"
2011-06-19 09:26:39 -04:00
result = react env
2011-05-23 04:07:54 -04:00
end
2011-06-19 09:26:39 -04:00
result or app.call(env)
end
def react(env)
result = send(options[:reaction], env)
result if Array === result and result.size == 3
2011-05-23 04:07:54 -04:00
end
def warn(env, message)
return unless options[:logging]
l = options[:logger] || env['rack.logger'] || ::Logger.new(env['rack.errors'])
l.warn(message)
end
2011-05-25 06:27:18 -04:00
def deny(env)
[options[:status], {'Content-Type' => 'text/plain'}, [options[:message]]]
end
2011-05-29 07:01:47 -04:00
def session?(env)
env.include? options[:session_key]
end
def session(env)
2011-05-29 07:01:47 -04:00
return env[options[:session_key]] if session? env
fail "you need to set up a session middleware *before* #{self.class}"
end
def drop_session(env)
session(env).clear if session? env
end
def referrer(env)
ref = env['HTTP_REFERER'].to_s
return if !options[:allow_empty_referrer] and ref.empty?
URI.parse(ref).host || Request.new(env).host
end
def origin(env)
env['HTTP_ORIGIN'] || env['HTTP_X_ORIGIN']
end
def random_string(secure = defined? SecureRandom)
secure ? SecureRandom.hex(32) : "%032x" % rand(2**128-1)
2011-11-08 09:44:32 -05:00
rescue NotImplementedError
random_string false
end
2011-05-29 07:01:47 -04:00
def encrypt(value)
options[:encryptor].hexdigest value.to_s
end
2011-06-20 03:16:15 -04:00
alias default_reaction deny
2011-05-23 04:07:54 -04:00
end
end
end