Class: Rack::Protection::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb

Constant Summary collapse

DEFAULT_OPTIONS =
{
  :reaction    => :default_reaction, :logging   => true,
  :message     => 'Forbidden',       :encryptor => Digest::SHA1,
  :session_key => 'rack.session',    :status    => 403,
  :allow_empty_referrer => true,
  :report_key           => "protection.failed",
  :html_types           => %w[text/html application/xhtml]
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Base

Returns a new instance of Base.



32
33
34
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 32

def initialize(app, options = {})
  @app, @options = app, default_options.merge(options)
end

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



18
19
20
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 18

def app
  @app
end

#optionsObject (readonly)

Returns the value of attribute options.



18
19
20
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 18

def options
  @options
end

Class Method Details

.default_options(options) ⇒ Object



20
21
22
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 20

def self.default_options(options)
  define_method(:default_options) { super().merge(options) }
end

.default_reaction(reaction) ⇒ Object



24
25
26
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 24

def self.default_reaction(reaction)
  alias_method(:default_reaction, reaction)
end

Instance Method Details

#accepts?(env) ⇒ Boolean

Returns:

  • (Boolean)

Raises:

  • (NotImplementedError)


40
41
42
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 40

def accepts?(env)
  raise NotImplementedError, "#{self.class} implementation pending"
end

#call(env) ⇒ Object



44
45
46
47
48
49
50
51
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 44

def call(env)
  unless accepts? env
    warn env, "attack prevented by #{self.class}"
    instrument env
    result = react env
  end
  result or app.call(env)
end

#default_optionsObject



28
29
30
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 28

def default_options
  DEFAULT_OPTIONS
end

#deny(env) ⇒ Object Also known as: default_reaction



70
71
72
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 70

def deny(env)
  [options[:status], {'Content-Type' => 'text/plain'}, [options[:message]]]
end

#drop_session(env) ⇒ Object



87
88
89
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 87

def drop_session(env)
  session(env).clear if session? env
end

#encrypt(value) ⇒ Object



107
108
109
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 107

def encrypt(value)
  options[:encryptor].hexdigest value.to_s
end

#html?(headers) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
116
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 113

def html?(headers)
  return false unless header = headers.detect { |k,v| k.downcase == 'content-type' }
  options[:html_types].include? header.last[/^\w+\/\w+/]
end

#instrument(env) ⇒ Object



64
65
66
67
68
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 64

def instrument(env)
  return unless i = options[:instrumenter]
  env['rack.protection.attack'] = self.class.name.split('::').last.downcase
  i.instrument('rack.protection', env)
end

#origin(env) ⇒ Object



97
98
99
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 97

def origin(env)
  env['HTTP_ORIGIN'] || env['HTTP_X_ORIGIN']
end

#random_string(secure = defined? SecureRandom)) ⇒ Object



101
102
103
104
105
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 101

def random_string(secure = defined? SecureRandom)
  secure ? SecureRandom.hex(16) : "%032x" % rand(2**128-1)
rescue NotImplementedError
  random_string false
end

#react(env) ⇒ Object



53
54
55
56
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 53

def react(env)
  result = send(options[:reaction], env)
  result if Array === result and result.size == 3
end

#referrer(env) ⇒ Object



91
92
93
94
95
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 91

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

#report(env) ⇒ Object



74
75
76
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 74

def report(env)
  env[options[:report_key]] = true
end

#safe?(env) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 36

def safe?(env)
  %w[GET HEAD OPTIONS TRACE].include? env['REQUEST_METHOD']
end

#session(env) ⇒ Object



82
83
84
85
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 82

def session(env)
  return env[options[:session_key]] if session? env
  fail "you need to set up a session middleware *before* #{self.class}"
end

#session?(env) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 78

def session?(env)
  env.include? options[:session_key]
end

#warn(env, message) ⇒ Object



58
59
60
61
62
# File 'lib/vendor/rack-protection-1.5.1/lib/rack/protection/base.rb', line 58

def warn(env, message)
  return unless options[:logging]
  l = options[:logger] || env['rack.logger'] || ::Logger.new(env['rack.errors'])
  l.warn(message)
end