sqreen 1.18.2-java → 1.18.3-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/LICENSE +3 -0
- data/lib/sqreen/actions.rb +11 -337
- data/lib/sqreen/actions/base.rb +110 -0
- data/lib/sqreen/actions/block_ip.rb +32 -0
- data/lib/sqreen/actions/block_user.rb +44 -0
- data/lib/sqreen/actions/ip_range_indexed_action_class.rb +36 -0
- data/lib/sqreen/actions/ip_ranges_index.rb +36 -0
- data/lib/sqreen/actions/redirect_ip.rb +40 -0
- data/lib/sqreen/actions/redirect_user.rb +45 -0
- data/lib/sqreen/actions/repository.rb +24 -0
- data/lib/sqreen/actions/unknown_action_type.rb +16 -0
- data/lib/sqreen/actions/user_action_class.rb +41 -0
- data/lib/sqreen/agent.rb +4 -1
- data/lib/sqreen/attack_blocked.rb +17 -0
- data/lib/sqreen/binding_accessor.rb +9 -102
- data/lib/sqreen/binding_accessor/path_elem.rb +8 -0
- data/lib/sqreen/binding_accessor/transforms.rb +107 -0
- data/lib/sqreen/capped_queue.rb +2 -0
- data/lib/sqreen/{callbacks.rb → cb.rb} +1 -53
- data/lib/sqreen/{callback_tree.rb → cb_tree.rb} +2 -2
- data/lib/sqreen/condition_evaluator.rb +22 -5
- data/lib/sqreen/configuration.rb +5 -0
- data/lib/sqreen/default_cb.rb +20 -0
- data/lib/sqreen/deferred_logger.rb +63 -0
- data/lib/sqreen/deliveries.rb +10 -0
- data/lib/sqreen/deliveries/batch.rb +7 -1
- data/lib/sqreen/deliveries/simple.rb +5 -0
- data/lib/sqreen/dependency/detector.rb +1 -1
- data/lib/sqreen/dependency/libsqreen.rb +28 -0
- data/lib/sqreen/dependency/rails.rb +4 -0
- data/lib/sqreen/dependency/sinatra.rb +47 -14
- data/lib/sqreen/error_handling_middleware.rb +30 -0
- data/lib/sqreen/event.rb +2 -0
- data/lib/sqreen/events/attack.rb +2 -0
- data/lib/sqreen/events/request_record.rb +11 -56
- data/lib/sqreen/exception.rb +9 -40
- data/lib/sqreen/formatter_with_tid.rb +45 -0
- data/lib/sqreen/framework_cb.rb +28 -0
- data/lib/sqreen/frameworks.rb +7 -0
- data/lib/sqreen/frameworks/generic.rb +20 -2
- data/lib/sqreen/frameworks/rails.rb +2 -0
- data/lib/sqreen/frameworks/request_recorder.rb +3 -0
- data/lib/sqreen/frameworks/sinatra.rb +2 -0
- data/lib/sqreen/frameworks/sqreen_test.rb +2 -0
- data/lib/sqreen/instrumentation.rb +5 -5
- data/lib/sqreen/invalid_signature_exception.rb +8 -0
- data/lib/{sqreen-alt.rb → sqreen/js.rb} +6 -1
- data/lib/sqreen/js/call_context.rb +10 -0
- data/lib/sqreen/js/context_pool.rb +60 -0
- data/lib/sqreen/js/exec_js_runnable.rb +20 -0
- data/lib/sqreen/js/execjs_adapter.rb +6 -47
- data/lib/sqreen/js/executable_js.rb +12 -0
- data/lib/sqreen/js/js_service.rb +2 -22
- data/lib/sqreen/js/js_service_adapter.rb +18 -0
- data/lib/sqreen/js/mini_racer_adapter.rb +6 -180
- data/lib/sqreen/js/mini_racer_executable_js.rb +142 -0
- data/lib/sqreen/js/thread_local_exec_js_runnable.rb +47 -0
- data/lib/sqreen/log.rb +8 -188
- data/lib/sqreen/logger.rb +83 -0
- data/lib/sqreen/metrics_store.rb +3 -11
- data/lib/sqreen/metrics_store/already_registered_metric.rb +11 -0
- data/lib/sqreen/metrics_store/unknown_metric.rb +11 -0
- data/lib/sqreen/metrics_store/unregistered_metric.rb +11 -0
- data/lib/sqreen/middleware.rb +0 -34
- data/lib/sqreen/mono_time.rb +2 -0
- data/lib/sqreen/node.rb +44 -0
- data/lib/sqreen/not_implemented_yet.rb +8 -0
- data/lib/sqreen/null_logger.rb +24 -0
- data/lib/sqreen/payload_creator.rb +2 -19
- data/lib/sqreen/payload_creator/header_section.rb +28 -0
- data/lib/sqreen/prefix.rb +33 -0
- data/lib/sqreen/rails_middleware.rb +14 -0
- data/lib/sqreen/remote_command.rb +1 -8
- data/lib/sqreen/remote_command/failure_output.rb +11 -0
- data/lib/sqreen/rules.rb +32 -2
- data/lib/sqreen/{rule_attributes.rb → rules/attrs.rb} +0 -0
- data/lib/sqreen/{rules_callbacks/sdk_auth_track.rb → rules/auth_track_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/binding_accessor_matcher.rb → rules/binding_accessor_matcher_cb.rb} +4 -8
- data/lib/sqreen/{rules_callbacks → rules}/binding_accessor_metrics.rb +1 -1
- data/lib/sqreen/{rules_callbacks/blacklist_ips.rb → rules/blacklist_ips_cb.rb} +3 -2
- data/lib/sqreen/{rules_callbacks → rules}/count_http_codes.rb +2 -2
- data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches.rb → rules/crawler_user_agent_matches_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches_metrics.rb → rules/crawler_user_agent_matches_metrics_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/custom_error.rb → rules/custom_error_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/devise_auth_track.rb → rules/devise_auth_track_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/devise_signup_track.rb → rules/devise_signup_track_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/execjs.rb → rules/execjs_cb.rb} +49 -50
- data/lib/sqreen/{rules_callbacks/headers_insert.rb → rules/headers_insert_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks → rules}/matcher_rule.rb +2 -2
- data/lib/sqreen/{rules_callbacks/not_found.rb → rules/not_found_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/rails_parameters.rb → rules/rails_parameters_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks → rules}/record_request_context.rb +1 -1
- data/lib/sqreen/{rules_callbacks/regexp_rule.rb → rules/regexp_rule_cb.rb} +1 -1
- data/lib/sqreen/{rule_callback.rb → rules/rule_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks → rules}/run_req_start_actions.rb +4 -2
- data/lib/sqreen/{rules_callbacks → rules}/run_user_actions.rb +1 -1
- data/lib/sqreen/{rules_callbacks/shell_env.rb → rules/shell_env_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/sdk_signup_track.rb → rules/signup_track_cb.rb} +2 -2
- data/lib/sqreen/rules/update_request_context.rb +20 -0
- data/lib/sqreen/{rules_callbacks/url_matches.rb → rules/url_matches_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/user_agent_matches.rb → rules/user_agent_matches_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/waf.rb → rules/waf_cb.rb} +10 -14
- data/lib/sqreen/{rules_callbacks/reflected_xss.rb → rules/xss_cb.rb} +10 -7
- data/lib/sqreen/run_when_called_cb.rb +21 -0
- data/lib/sqreen/runtime_infos.rb +2 -9
- data/lib/sqreen/sensitive_data_redactor.rb +111 -0
- data/lib/sqreen/signature_verifier.rb +20 -0
- data/lib/sqreen/sinatra_middleware.rb +14 -0
- data/lib/sqreen/{rules_signature.rb → sqreen_signed_verifier.rb} +5 -17
- data/lib/sqreen/token_invalid_exception.rb +8 -0
- data/lib/sqreen/token_not_found_exception.rb +9 -0
- data/lib/sqreen/trie.rb +3 -64
- data/lib/sqreen/unauthorized.rb +8 -0
- data/lib/sqreen/util.rb +2 -0
- data/lib/sqreen/util/capped_array.rb +33 -0
- data/lib/sqreen/util/capped_hash.rb +39 -0
- data/lib/sqreen/util/capped_string.rb +24 -0
- data/lib/sqreen/util/capper.rb +65 -0
- data/lib/sqreen/version.rb +1 -1
- data/lib/sqreen/waf_error.rb +18 -0
- metadata +87 -35
- data/lib/sqreen/rules_callbacks.rb +0 -35
- data/lib/sqreen/rules_callbacks/inspect_rule.rb +0 -25
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
require 'cgi'
|
|
5
5
|
|
|
6
|
-
require 'sqreen/
|
|
7
|
-
require 'sqreen/
|
|
6
|
+
require 'sqreen/rules/rule_cb'
|
|
7
|
+
require 'sqreen/rules/regexp_rule_cb'
|
|
8
8
|
|
|
9
9
|
# Sqreen module
|
|
10
10
|
module Sqreen
|
|
@@ -21,6 +21,7 @@ module Sqreen
|
|
|
21
21
|
return nil unless framework
|
|
22
22
|
framework.xss_params(@union_pattern)
|
|
23
23
|
end
|
|
24
|
+
|
|
24
25
|
# The remaining code is only to find out if user entry was an attack,
|
|
25
26
|
# and record it. Since we don't rely on it to respond to user, it would
|
|
26
27
|
# be better to do it in background.
|
|
@@ -36,6 +37,7 @@ module Sqreen
|
|
|
36
37
|
true
|
|
37
38
|
end
|
|
38
39
|
end
|
|
40
|
+
|
|
39
41
|
class ReflectedUnsafeXSSCB < XSSCB
|
|
40
42
|
def pre(_inst, args, _budget = nil, &_block)
|
|
41
43
|
value = args[0]
|
|
@@ -52,13 +54,12 @@ module Sqreen
|
|
|
52
54
|
return unless report_dangerous_xss?(saved_value)
|
|
53
55
|
|
|
54
56
|
# potential XSS! let's escape
|
|
55
|
-
if block
|
|
56
|
-
args[0].replace(CGI.escape_html(value))
|
|
57
|
-
end
|
|
57
|
+
args[0].replace(CGI.escape_html(value)) if block
|
|
58
58
|
|
|
59
59
|
advise_action(nil)
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
|
+
|
|
62
63
|
# look for reflected XSS with erb template engine
|
|
63
64
|
class ReflectedXSSCB < XSSCB
|
|
64
65
|
def pre(_inst, args, _budget = nil, &_block)
|
|
@@ -84,6 +85,7 @@ module Sqreen
|
|
|
84
85
|
advise_action(nil)
|
|
85
86
|
end
|
|
86
87
|
end
|
|
88
|
+
|
|
87
89
|
# look for reflected XSS with haml template engine
|
|
88
90
|
# hook function arguments of
|
|
89
91
|
# Haml::Buffer.format_script(result, preserve_script, in_tag, preserve_tag,
|
|
@@ -145,7 +147,7 @@ module Sqreen
|
|
|
145
147
|
if tag.value[:escape_html] == false &&
|
|
146
148
|
tag.value[:value].respond_to?(:include?) &&
|
|
147
149
|
!tag.value[:value].include?('html_escape') &&
|
|
148
|
-
|
|
150
|
+
tag.value[:parse] == true
|
|
149
151
|
tag.value[:value] = "Sqreen.escape_haml((#{tag.value[:value]}))"
|
|
150
152
|
return { :status => :override, :new_return_value => tag }
|
|
151
153
|
end
|
|
@@ -172,7 +174,8 @@ module Sqreen
|
|
|
172
174
|
res << '#{'
|
|
173
175
|
else
|
|
174
176
|
# Use eval to get rid of string escapes
|
|
175
|
-
|
|
177
|
+
# TODO: look for eval removal
|
|
178
|
+
content = eval('"' + Haml::Util.balance(scan, '{', '}', 1)[0][0...-1] + '"') # rubocop:disable Security/Eval
|
|
176
179
|
content = "Haml::Helpers.html_escape((#{content}))" if escape_html
|
|
177
180
|
res << '#{Sqreen.escape_haml((' + content + '))}'
|
|
178
181
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
|
+
|
|
4
|
+
require 'sqreen/cb'
|
|
5
|
+
|
|
6
|
+
module Sqreen
|
|
7
|
+
class RunWhenCalledCB < CB
|
|
8
|
+
def initialize(klass, method, &block)
|
|
9
|
+
super(klass, method)
|
|
10
|
+
|
|
11
|
+
raise 'missing block' unless block_given?
|
|
12
|
+
@block = block
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def pre(_inst, _args, _budget = nil, &_block)
|
|
16
|
+
# FIXME: implement this removal
|
|
17
|
+
@remove_me = true
|
|
18
|
+
@block.call
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/sqreen/runtime_infos.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
require 'sqreen/version'
|
|
5
5
|
require 'sqreen/frameworks'
|
|
6
|
+
require 'sqreen/dependency/libsqreen'
|
|
6
7
|
|
|
7
8
|
require 'socket'
|
|
8
9
|
require 'digest/sha1'
|
|
@@ -71,15 +72,7 @@ module Sqreen
|
|
|
71
72
|
end
|
|
72
73
|
|
|
73
74
|
def libsqreen?
|
|
74
|
-
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def libsqreen_loaded?
|
|
78
|
-
Kernel.const_defined?('LibSqreen')
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def libsqreen_stub?
|
|
82
|
-
!::LibSqreen.respond_to?(:version)
|
|
75
|
+
Sqreen::Dependency::LibSqreen.required? && !Sqreen::Dependency::LibSqreen.stub?
|
|
83
76
|
end
|
|
84
77
|
|
|
85
78
|
def libsqreen_version
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
|
+
|
|
4
|
+
# TODO: Sqreen.config_get
|
|
5
|
+
|
|
6
|
+
require 'json'
|
|
7
|
+
require 'sqreen/log'
|
|
8
|
+
|
|
9
|
+
module Sqreen
|
|
10
|
+
# For redacting sensitive data and avoid having it sent to our servers
|
|
11
|
+
class SensitiveDataRedactor
|
|
12
|
+
DEFAULT_SENSITIVE_KEYS = Set.new(%w[password secret passwd authorization api_key apikey access_token]).freeze
|
|
13
|
+
DEFAULT_REGEX = /\A(?:\d[ -]*?){13,16}\z/
|
|
14
|
+
MASK = '<Redacted by Sqreen>'.freeze
|
|
15
|
+
|
|
16
|
+
def self.from_config
|
|
17
|
+
keys = Sqreen.config_get(:strip_sensitive_keys)
|
|
18
|
+
keys = keys.split(',') if keys && keys.is_a?(String)
|
|
19
|
+
|
|
20
|
+
regex = Sqreen.config_get(:strip_sensitive_regex)
|
|
21
|
+
if regex && regex.is_a?(String)
|
|
22
|
+
begin
|
|
23
|
+
regex = Regexp.compile(regex)
|
|
24
|
+
rescue RegexpError
|
|
25
|
+
Sqreen.log.warn("Invalid regular expression given in strip_sensitive_regex: #{regex}")
|
|
26
|
+
regex = nil
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
regex = nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
new(keys: keys, regex: regex)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def initialize(params = {})
|
|
36
|
+
@regex = params[:regex] || DEFAULT_REGEX
|
|
37
|
+
@keys = (params[:keys] || DEFAULT_SENSITIVE_KEYS).map(&:downcase)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def redact(obj)
|
|
41
|
+
result = obj
|
|
42
|
+
redacted = []
|
|
43
|
+
|
|
44
|
+
case obj
|
|
45
|
+
when String
|
|
46
|
+
if obj =~ @regex
|
|
47
|
+
result = MASK
|
|
48
|
+
redacted << obj
|
|
49
|
+
end
|
|
50
|
+
when Array
|
|
51
|
+
result = []
|
|
52
|
+
obj.each do |e|
|
|
53
|
+
e, r = redact(e)
|
|
54
|
+
result << e
|
|
55
|
+
redacted += r
|
|
56
|
+
end
|
|
57
|
+
when Hash
|
|
58
|
+
result = {}
|
|
59
|
+
obj.each do |k, v|
|
|
60
|
+
ck = k.is_a?(String) ? k.downcase : k
|
|
61
|
+
if @keys.include?(ck)
|
|
62
|
+
redacted << v
|
|
63
|
+
v = MASK
|
|
64
|
+
else
|
|
65
|
+
v, r = redact(v)
|
|
66
|
+
redacted += r
|
|
67
|
+
end
|
|
68
|
+
result[k] = v
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
[result, redacted]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def redact_attacks!(attacks, values)
|
|
76
|
+
return attacks if values.empty?
|
|
77
|
+
|
|
78
|
+
values = values.map { |v| v.downcase if v.is_a?(String) }
|
|
79
|
+
|
|
80
|
+
attacks.each do |e|
|
|
81
|
+
next(e) unless e[:infos]
|
|
82
|
+
next(e) unless e[:infos][:waf_data]
|
|
83
|
+
|
|
84
|
+
parsed = JSON.parse(e[:infos][:waf_data])
|
|
85
|
+
redacted = parsed.each do |w|
|
|
86
|
+
next unless (filters = w['filter'])
|
|
87
|
+
|
|
88
|
+
filters.each do |f|
|
|
89
|
+
next unless (v = f['resolved_value'])
|
|
90
|
+
next unless values.include?(v.downcase)
|
|
91
|
+
|
|
92
|
+
f['match_status'] = MASK
|
|
93
|
+
f['resolved_value'] = MASK
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
e[:infos][:waf_data] = JSON.dump(redacted)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def redact_exceptions!(exceptions, values)
|
|
101
|
+
return exceptions if values.empty?
|
|
102
|
+
|
|
103
|
+
exceptions.each do |e|
|
|
104
|
+
next(e) unless e[:infos]
|
|
105
|
+
next(e) unless e[:infos][:waf]
|
|
106
|
+
|
|
107
|
+
e[:infos][:waf].delete(:args)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
|
+
|
|
4
|
+
require 'openssl'
|
|
5
|
+
|
|
6
|
+
## Rules signature
|
|
7
|
+
module Sqreen
|
|
8
|
+
# Perform an EC + digest verification of a message.
|
|
9
|
+
class SignatureVerifier
|
|
10
|
+
def initialize(key, digest)
|
|
11
|
+
@pub_key = OpenSSL::PKey.read(key)
|
|
12
|
+
@digest = digest
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def verify(sig, val)
|
|
16
|
+
hashed_val = @digest.digest(val)
|
|
17
|
+
@pub_key.dsa_verify_asn1(hashed_val, sig)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
|
+
|
|
4
|
+
module Sqreen
|
|
5
|
+
class SinatraMiddleware
|
|
6
|
+
def initialize(app)
|
|
7
|
+
@app = app
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(env)
|
|
11
|
+
@app.call(env)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
2
2
|
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
3
|
|
|
4
|
-
require 'sqreen/exception'
|
|
5
|
-
|
|
6
4
|
require 'set'
|
|
7
5
|
require 'openssl'
|
|
8
6
|
require 'base64'
|
|
@@ -18,21 +16,11 @@ else
|
|
|
18
16
|
end
|
|
19
17
|
end
|
|
20
18
|
|
|
19
|
+
require 'sqreen/exception'
|
|
20
|
+
require 'sqreen/signature_verifier'
|
|
21
|
+
|
|
21
22
|
## Rules signature
|
|
22
23
|
module Sqreen
|
|
23
|
-
# Perform an EC + digest verification of a message.
|
|
24
|
-
class SignatureVerifier
|
|
25
|
-
def initialize(key, digest)
|
|
26
|
-
@pub_key = OpenSSL::PKey.read(key)
|
|
27
|
-
@digest = digest
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def verify(sig, val)
|
|
31
|
-
hashed_val = @digest.digest(val)
|
|
32
|
-
@pub_key.dsa_verify_asn1(hashed_val, sig)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
24
|
# Normalize and verify a rule
|
|
37
25
|
class SqreenSignedVerifier
|
|
38
26
|
REQUIRED_SIGNED_KEYS = %w[hookpoint name callbacks conditions].freeze
|
|
@@ -40,14 +28,14 @@ module Sqreen
|
|
|
40
28
|
SIGNATURE_VALUE_KEY = 'value'.freeze
|
|
41
29
|
SIGNED_KEYS_KEY = 'keys'.freeze
|
|
42
30
|
SIGNATURE_VERSION = 'v0_9'.freeze
|
|
43
|
-
PUBLIC_KEY = <<-
|
|
31
|
+
PUBLIC_KEY = <<-KEY.gsub(/^ */, '').freeze
|
|
44
32
|
-----BEGIN PUBLIC KEY-----
|
|
45
33
|
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQA39oWMHR8sxb9LRaM5evZ7mw03iwJ
|
|
46
34
|
WNHuDeGqgPo1HmvuMfLnAyVLwaMXpGPuvbqhC1U65PG90bTJLpvNokQf0VMA5Tpi
|
|
47
35
|
m+NXwl7bjqa03vO/HErLbq3zBRysrZnC4OhJOF1jazkAg0psQOea2r5HcMcPHgMK
|
|
48
36
|
fnWXiKWnZX+uOWPuerE=
|
|
49
37
|
-----END PUBLIC KEY-----
|
|
50
|
-
|
|
38
|
+
KEY
|
|
51
39
|
|
|
52
40
|
attr_accessor :pub_key
|
|
53
41
|
attr_accessor :required_signed_keys
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
|
+
|
|
4
|
+
require 'sqreen/exception'
|
|
5
|
+
|
|
6
|
+
module Sqreen
|
|
7
|
+
# When the token is not found
|
|
8
|
+
class TokenNotFoundException < Sqreen::Exception; end
|
|
9
|
+
end
|
data/lib/sqreen/trie.rb
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
3
|
|
|
4
4
|
require 'ipaddr'
|
|
5
|
+
require 'sqreen/node'
|
|
6
|
+
|
|
7
|
+
# TODO: move to Sqreen::IP
|
|
5
8
|
|
|
6
9
|
module Sqreen
|
|
7
10
|
Trie = Struct.new(:head, :num_active_nodes, :family) do
|
|
@@ -211,68 +214,4 @@ module Sqreen
|
|
|
211
214
|
xstack
|
|
212
215
|
end
|
|
213
216
|
end
|
|
214
|
-
|
|
215
|
-
Prefix = Struct.new(:family, :bitlen, :address, :data) do # addr is integer
|
|
216
|
-
def initialize(*args)
|
|
217
|
-
super
|
|
218
|
-
raise ArgumentError, 'no family given' unless family
|
|
219
|
-
raise ArgumentError, 'no bitlen given' unless bitlen
|
|
220
|
-
raise ArgumentError, 'no address given' unless address
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
def matches?(addr, family)
|
|
224
|
-
raise 'family mismatch' unless family == self.family
|
|
225
|
-
shift_amount = (family == Socket::AF_INET ? 32 : 128) - self.bitlen
|
|
226
|
-
(addr ^ self.address) >> shift_amount == 0
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
def Prefix.from_str(str, data = nil)
|
|
231
|
-
ip_addr = IPAddr.new(str)
|
|
232
|
-
if str =~ /\/(\d+)$/
|
|
233
|
-
bitlen = $~[1].to_i
|
|
234
|
-
else
|
|
235
|
-
bitlen = ip_addr.family == Socket::AF_INET6 ? 128 : 32
|
|
236
|
-
end
|
|
237
|
-
Prefix.new(ip_addr.family, bitlen, ip_addr.to_i, data)
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
# bit starts at 0 (most significant)
|
|
241
|
-
Node = Struct.new(:bit, :prefix, :l, :r, :parent) do
|
|
242
|
-
def initialize(*args)
|
|
243
|
-
super
|
|
244
|
-
raise ArgumentError, 'no bit given' if bit.nil?
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
def empty?
|
|
248
|
-
prefix.nil?
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
# cover the whole tree
|
|
252
|
-
def walk(max_bits, empty_nodes = false)
|
|
253
|
-
xstack = Array.new(max_bits + 1)
|
|
254
|
-
sidx = 0 # stack index
|
|
255
|
-
xhead = self
|
|
256
|
-
xcur = xhead
|
|
257
|
-
while !xcur.nil?
|
|
258
|
-
yield xcur unless xcur.empty? && !empty_nodes
|
|
259
|
-
|
|
260
|
-
if xcur.l
|
|
261
|
-
if xcur.r
|
|
262
|
-
xstack[sidx] = xcur.r
|
|
263
|
-
sidx += 1
|
|
264
|
-
end
|
|
265
|
-
xcur = xcur.l
|
|
266
|
-
elsif xcur.r
|
|
267
|
-
xcur = xcur.r
|
|
268
|
-
elsif sidx.nonzero?
|
|
269
|
-
sidx -= 1
|
|
270
|
-
xcur = xstack[sidx]
|
|
271
|
-
else
|
|
272
|
-
xcur = nil
|
|
273
|
-
end
|
|
274
|
-
end
|
|
275
|
-
end
|
|
276
|
-
end
|
|
277
|
-
|
|
278
217
|
end
|
data/lib/sqreen/util.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
|
+
|
|
4
|
+
require 'sqreen/util'
|
|
5
|
+
|
|
6
|
+
class Sqreen::Util::CappedArray < Array
|
|
7
|
+
attr_reader :size_cap, :depth_cap
|
|
8
|
+
|
|
9
|
+
def initialize(*args, &block)
|
|
10
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
|
11
|
+
size_cap = opts[:size_cap] || 150
|
|
12
|
+
depth_cap = opts[:depth_cap] || 10
|
|
13
|
+
@size_cap = size_cap
|
|
14
|
+
@depth_cap = depth_cap
|
|
15
|
+
|
|
16
|
+
super(*args, &block)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def <<(value)
|
|
20
|
+
keep?(size, value) ? super : self
|
|
21
|
+
end
|
|
22
|
+
alias_method :append, :<<
|
|
23
|
+
|
|
24
|
+
def []=(index, value)
|
|
25
|
+
super if keep?(index, value)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def keep?(index, value)
|
|
31
|
+
index < size_cap && (depth_cap > 0 || !value.is_a?(Hash) && !value.is_a?(Array))
|
|
32
|
+
end
|
|
33
|
+
end
|