newrelic_security 0.1.0
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 +7 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/enhancement.md +27 -0
- data/.github/actions/simplecov-report/LICENSE +22 -0
- data/.github/actions/simplecov-report/README.md +36 -0
- data/.github/actions/simplecov-report/__tests__/.keep +0 -0
- data/.github/actions/simplecov-report/__tests__/main.test.ts +3 -0
- data/.github/actions/simplecov-report/action.yml +25 -0
- data/.github/actions/simplecov-report/dist/index.js +10238 -0
- data/.github/actions/simplecov-report/dummy_coverage/.last_run.json +5 -0
- data/.github/actions/simplecov-report/jest.config.js +11 -0
- data/.github/actions/simplecov-report/package.json +51 -0
- data/.github/actions/simplecov-report/src/main.ts +54 -0
- data/.github/actions/simplecov-report/src/report.ts +28 -0
- data/.github/actions/simplecov-report/tsconfig.json +12 -0
- data/.github/workflows/pr_ci.yml +77 -0
- data/.github/workflows/release.yml +51 -0
- data/.github/workflows/repolinter.yml +31 -0
- data/.github/workflows/rubocop.yml +17 -0
- data/.github/workflows/scripts/rubygems-authenticate.py +13 -0
- data/.github/workflows/scripts/rubygems-publish.rb +33 -0
- data/.gitignore +72 -0
- data/.rubocop.yml +9 -0
- data/.rubocop_todo.yml +1414 -0
- data/.simplecov +16 -0
- data/CHANGELOG.md +69 -0
- data/CONTRIBUTING.md +22 -0
- data/Gemfile +6 -0
- data/Gemfile_test +58 -0
- data/LICENSE +43 -0
- data/README.md +133 -0
- data/README_agent.md +44 -0
- data/Rakefile +28 -0
- data/THIRD_PARTY_NOTICES.md +36 -0
- data/lib/newrelic_security/agent/agent.rb +109 -0
- data/lib/newrelic_security/agent/configuration/default_source.rb +8 -0
- data/lib/newrelic_security/agent/configuration/environment_source.rb +8 -0
- data/lib/newrelic_security/agent/configuration/manager.rb +178 -0
- data/lib/newrelic_security/agent/configuration/manual_source.rb +8 -0
- data/lib/newrelic_security/agent/configuration/server_source.rb +8 -0
- data/lib/newrelic_security/agent/configuration/yaml_source.rb +8 -0
- data/lib/newrelic_security/agent/control/app_info.rb +132 -0
- data/lib/newrelic_security/agent/control/application_url_mappings.rb +66 -0
- data/lib/newrelic_security/agent/control/collector.rb +117 -0
- data/lib/newrelic_security/agent/control/control_command.rb +117 -0
- data/lib/newrelic_security/agent/control/critical_message.rb +58 -0
- data/lib/newrelic_security/agent/control/event.rb +149 -0
- data/lib/newrelic_security/agent/control/event_counter.rb +28 -0
- data/lib/newrelic_security/agent/control/event_processor.rb +134 -0
- data/lib/newrelic_security/agent/control/event_stats.rb +26 -0
- data/lib/newrelic_security/agent/control/event_subscriber.rb +28 -0
- data/lib/newrelic_security/agent/control/exit_event.rb +38 -0
- data/lib/newrelic_security/agent/control/fuzz_request.rb +18 -0
- data/lib/newrelic_security/agent/control/grpc_context.rb +57 -0
- data/lib/newrelic_security/agent/control/health_check.rb +136 -0
- data/lib/newrelic_security/agent/control/http_context.rb +73 -0
- data/lib/newrelic_security/agent/control/iast_client.rb +151 -0
- data/lib/newrelic_security/agent/control/iast_data_transfer_request.rb +32 -0
- data/lib/newrelic_security/agent/control/reflected_xss.rb +258 -0
- data/lib/newrelic_security/agent/control/websocket_client.rb +131 -0
- data/lib/newrelic_security/agent/logging/init_logger.rb +91 -0
- data/lib/newrelic_security/agent/logging/logger.rb +92 -0
- data/lib/newrelic_security/agent/logging/null_logger.rb +21 -0
- data/lib/newrelic_security/agent/resources/cert.pem +50 -0
- data/lib/newrelic_security/agent/utils/agent_utils.rb +219 -0
- data/lib/newrelic_security/agent.rb +57 -0
- data/lib/newrelic_security/constants.rb +67 -0
- data/lib/newrelic_security/instrumentation-security/active_record/mysql2_adapter/chain.rb +70 -0
- data/lib/newrelic_security/instrumentation-security/active_record/mysql2_adapter/instrumentation.rb +187 -0
- data/lib/newrelic_security/instrumentation-security/active_record/mysql2_adapter/prepend.rb +54 -0
- data/lib/newrelic_security/instrumentation-security/active_record/postgresql_adapter/chain.rb +60 -0
- data/lib/newrelic_security/instrumentation-security/active_record/postgresql_adapter/instrumentation.rb +143 -0
- data/lib/newrelic_security/instrumentation-security/active_record/postgresql_adapter/prepend.rb +48 -0
- data/lib/newrelic_security/instrumentation-security/active_record/sqlite3_adapter/chain.rb +72 -0
- data/lib/newrelic_security/instrumentation-security/active_record/sqlite3_adapter/instrumentation.rb +187 -0
- data/lib/newrelic_security/instrumentation-security/active_record/sqlite3_adapter/prepend.rb +54 -0
- data/lib/newrelic_security/instrumentation-security/async-http/chain.rb +21 -0
- data/lib/newrelic_security/instrumentation-security/async-http/instrumentation.rb +46 -0
- data/lib/newrelic_security/instrumentation-security/async-http/prepend.rb +16 -0
- data/lib/newrelic_security/instrumentation-security/curb/chain.rb +26 -0
- data/lib/newrelic_security/instrumentation-security/curb/instrumentation.rb +52 -0
- data/lib/newrelic_security/instrumentation-security/curb/prepend.rb +18 -0
- data/lib/newrelic_security/instrumentation-security/dir/chain.rb +42 -0
- data/lib/newrelic_security/instrumentation-security/dir/instrumentation.rb +102 -0
- data/lib/newrelic_security/instrumentation-security/dir/prepend.rb +28 -0
- data/lib/newrelic_security/instrumentation-security/ethon/chain.rb +53 -0
- data/lib/newrelic_security/instrumentation-security/ethon/instrumentation.rb +122 -0
- data/lib/newrelic_security/instrumentation-security/ethon/prepend.rb +39 -0
- data/lib/newrelic_security/instrumentation-security/excon/chain.rb +23 -0
- data/lib/newrelic_security/instrumentation-security/excon/instrumentation.rb +44 -0
- data/lib/newrelic_security/instrumentation-security/excon/prepend.rb +17 -0
- data/lib/newrelic_security/instrumentation-security/file/chain.rb +34 -0
- data/lib/newrelic_security/instrumentation-security/file/instrumentation.rb +62 -0
- data/lib/newrelic_security/instrumentation-security/file/prepend.rb +22 -0
- data/lib/newrelic_security/instrumentation-security/grape/chain.rb +42 -0
- data/lib/newrelic_security/instrumentation-security/grape/instrumentation.rb +56 -0
- data/lib/newrelic_security/instrumentation-security/grape/prepend.rb +30 -0
- data/lib/newrelic_security/instrumentation-security/grpc/client/chain.rb +47 -0
- data/lib/newrelic_security/instrumentation-security/grpc/client/instrumentation.rb +37 -0
- data/lib/newrelic_security/instrumentation-security/grpc/client/prepend.rb +36 -0
- data/lib/newrelic_security/instrumentation-security/grpc/server/chain.rb +62 -0
- data/lib/newrelic_security/instrumentation-security/grpc/server/instrumentation.rb +65 -0
- data/lib/newrelic_security/instrumentation-security/grpc/server/prepend.rb +46 -0
- data/lib/newrelic_security/instrumentation-security/httpclient/chain.rb +30 -0
- data/lib/newrelic_security/instrumentation-security/httpclient/instrumentation.rb +82 -0
- data/lib/newrelic_security/instrumentation-security/httpclient/prepend.rb +22 -0
- data/lib/newrelic_security/instrumentation-security/httprb/chain.rb +21 -0
- data/lib/newrelic_security/instrumentation-security/httprb/instrumentation.rb +44 -0
- data/lib/newrelic_security/instrumentation-security/httprb/prepend.rb +16 -0
- data/lib/newrelic_security/instrumentation-security/httpx/chain.rb +23 -0
- data/lib/newrelic_security/instrumentation-security/httpx/instrumentation.rb +51 -0
- data/lib/newrelic_security/instrumentation-security/httpx/prepend.rb +18 -0
- data/lib/newrelic_security/instrumentation-security/instrumentation_loader.rb +50 -0
- data/lib/newrelic_security/instrumentation-security/instrumentation_utils.rb +165 -0
- data/lib/newrelic_security/instrumentation-security/io/chain.rb +113 -0
- data/lib/newrelic_security/instrumentation-security/io/instrumentation.rb +300 -0
- data/lib/newrelic_security/instrumentation-security/io/prepend.rb +86 -0
- data/lib/newrelic_security/instrumentation-security/kernel/chain.rb +65 -0
- data/lib/newrelic_security/instrumentation-security/kernel/instrumentation.rb +167 -0
- data/lib/newrelic_security/instrumentation-security/kernel/prepend.rb +50 -0
- data/lib/newrelic_security/instrumentation-security/mongo/chain.rb +106 -0
- data/lib/newrelic_security/instrumentation-security/mongo/instrumentation.rb +273 -0
- data/lib/newrelic_security/instrumentation-security/mongo/prepend.rb +77 -0
- data/lib/newrelic_security/instrumentation-security/mysql2/chain.rb +53 -0
- data/lib/newrelic_security/instrumentation-security/mysql2/instrumentation.rb +84 -0
- data/lib/newrelic_security/instrumentation-security/mysql2/prepend.rb +37 -0
- data/lib/newrelic_security/instrumentation-security/net_http/chain.rb +21 -0
- data/lib/newrelic_security/instrumentation-security/net_http/instrumentation.rb +60 -0
- data/lib/newrelic_security/instrumentation-security/net_http/prepend.rb +16 -0
- data/lib/newrelic_security/instrumentation-security/net_ldap/chain.rb +21 -0
- data/lib/newrelic_security/instrumentation-security/net_ldap/instrumentation.rb +42 -0
- data/lib/newrelic_security/instrumentation-security/net_ldap/prepend.rb +16 -0
- data/lib/newrelic_security/instrumentation-security/nokogiri/chain.rb +46 -0
- data/lib/newrelic_security/instrumentation-security/nokogiri/instrumentation.rb +36 -0
- data/lib/newrelic_security/instrumentation-security/nokogiri/prepend.rb +31 -0
- data/lib/newrelic_security/instrumentation-security/padrino/chain.rb +26 -0
- data/lib/newrelic_security/instrumentation-security/padrino/instrumentation.rb +42 -0
- data/lib/newrelic_security/instrumentation-security/padrino/prepend.rb +20 -0
- data/lib/newrelic_security/instrumentation-security/patron/chain.rb +23 -0
- data/lib/newrelic_security/instrumentation-security/patron/instrumentation.rb +50 -0
- data/lib/newrelic_security/instrumentation-security/patron/prepend.rb +18 -0
- data/lib/newrelic_security/instrumentation-security/pg/chain.rb +49 -0
- data/lib/newrelic_security/instrumentation-security/pg/instrumentation.rb +102 -0
- data/lib/newrelic_security/instrumentation-security/pg/prepend.rb +36 -0
- data/lib/newrelic_security/instrumentation-security/pty/chain.rb +31 -0
- data/lib/newrelic_security/instrumentation-security/pty/instrumentation.rb +52 -0
- data/lib/newrelic_security/instrumentation-security/pty/prepend.rb +22 -0
- data/lib/newrelic_security/instrumentation-security/rails/chain.rb +46 -0
- data/lib/newrelic_security/instrumentation-security/rails/instrumentation.rb +67 -0
- data/lib/newrelic_security/instrumentation-security/rails/prepend.rb +33 -0
- data/lib/newrelic_security/instrumentation-security/roda/chain.rb +22 -0
- data/lib/newrelic_security/instrumentation-security/roda/instrumentation.rb +41 -0
- data/lib/newrelic_security/instrumentation-security/roda/prepend.rb +16 -0
- data/lib/newrelic_security/instrumentation-security/sinatra/chain.rb +29 -0
- data/lib/newrelic_security/instrumentation-security/sinatra/instrumentation.rb +49 -0
- data/lib/newrelic_security/instrumentation-security/sinatra/prepend.rb +21 -0
- data/lib/newrelic_security/instrumentation-security/sqlite3/chain.rb +79 -0
- data/lib/newrelic_security/instrumentation-security/sqlite3/instrumentation.rb +164 -0
- data/lib/newrelic_security/instrumentation-security/sqlite3/prepend.rb +56 -0
- data/lib/newrelic_security/newrelic-security-api/api.rb +72 -0
- data/lib/newrelic_security/version.rb +5 -0
- data/lib/newrelic_security/websocket-client-simple/client.rb +128 -0
- data/lib/newrelic_security/websocket-client-simple/event_emitter.rb +72 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/error.rb +129 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/exception_handler.rb +32 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/base.rb +62 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/data.rb +49 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/base.rb +41 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler03.rb +224 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler04.rb +18 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler05.rb +15 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler07.rb +78 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler75.rb +78 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler.rb +15 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/incoming/client.rb +17 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/incoming/server.rb +17 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/incoming.rb +52 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/outgoing/client.rb +17 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/outgoing/server.rb +17 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/outgoing.rb +35 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame.rb +11 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/base.rb +142 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/client.rb +130 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/base.rb +49 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client.rb +32 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client01.rb +20 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client04.rb +63 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client11.rb +22 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client75.rb +39 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client76.rb +105 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server.rb +10 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server04.rb +56 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server75.rb +40 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server76.rb +75 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler.rb +21 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/server.rb +179 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake.rb +10 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/nice_inspect.rb +12 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/version.rb +5 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket.rb +50 -0
- data/lib/newrelic_security.rb +6 -0
- data/lib/tasks/all.rb +8 -0
- data/lib/tasks/coverage_report.rake +27 -0
- data/newrelic_security.gemspec +51 -0
- metadata +342 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# encoding: binary
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NewRelic::Security::WebSocket
|
|
5
|
+
module Frame
|
|
6
|
+
module Handler
|
|
7
|
+
class Handler75 < Base
|
|
8
|
+
# @see NewRelic::Security::WebSocket::Frame::Base#supported_frames
|
|
9
|
+
def supported_frames
|
|
10
|
+
%i[text close]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @see NewRelic::Security::WebSocket::Frame::Handler::Base#encode_frame
|
|
14
|
+
def encode_frame
|
|
15
|
+
case @frame.type
|
|
16
|
+
when :close then "\xff\x00"
|
|
17
|
+
when :text then
|
|
18
|
+
ary = ["\x00", @frame.data, "\xff"]
|
|
19
|
+
ary.map { |s| s.encode('UTF-8', 'UTF-8', invalid: :replace) }
|
|
20
|
+
ary.join
|
|
21
|
+
else raise NewRelic::Security::WebSocket::Error::Frame::UnknownFrameType
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @see NewRelic::Security::WebSocket::Frame::Handler::Base#decode_frame
|
|
26
|
+
def decode_frame
|
|
27
|
+
return if @frame.data.size.zero?
|
|
28
|
+
|
|
29
|
+
pointer = 0
|
|
30
|
+
frame_type = @frame.data.getbyte(pointer)
|
|
31
|
+
pointer += 1
|
|
32
|
+
|
|
33
|
+
if (frame_type & 0x80) == 0x80
|
|
34
|
+
# If the high-order bit of the /frame type/ byte is set
|
|
35
|
+
length = 0
|
|
36
|
+
|
|
37
|
+
loop do
|
|
38
|
+
return unless @frame.data.getbyte(pointer)
|
|
39
|
+
b = @frame.data.getbyte(pointer)
|
|
40
|
+
pointer += 1
|
|
41
|
+
b_v = b & 0x7F
|
|
42
|
+
length = length * 128 + b_v
|
|
43
|
+
break unless (b & 0x80) == 0x80
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
raise NewRelic::Security::WebSocket::Error::Frame::TooLong if length > ::NewRelic::Security::WebSocket.max_frame_size
|
|
47
|
+
|
|
48
|
+
unless @frame.data.getbyte(pointer + length - 1).nil?
|
|
49
|
+
# Straight from spec - I'm sure this isn't crazy...
|
|
50
|
+
# 6. Read /length/ bytes.
|
|
51
|
+
# 7. Discard the read bytes.
|
|
52
|
+
@frame.instance_variable_set '@data', @frame.data[(pointer + length)..-1]
|
|
53
|
+
|
|
54
|
+
# If the /frame type/ is 0xFF and the /length/ was 0, then close
|
|
55
|
+
if length.zero?
|
|
56
|
+
@frame.class.new(version: @frame.version, type: :close, decoded: true)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
# If the high-order bit of the /frame type/ byte is _not_ set
|
|
61
|
+
|
|
62
|
+
raise NewRelic::Security::WebSocket::Error::Frame::Invalid if @frame.data.getbyte(0) != 0x00
|
|
63
|
+
|
|
64
|
+
# Addition to the spec to protect against malicious requests
|
|
65
|
+
raise NewRelic::Security::WebSocket::Error::Frame::TooLong if @frame.data.size > ::NewRelic::Security::WebSocket.max_frame_size
|
|
66
|
+
|
|
67
|
+
msg = @frame.data.slice!(/\A\x00[^\xff]*\xff/)
|
|
68
|
+
if msg
|
|
69
|
+
msg.gsub!(/\A\x00|\xff\z/, '')
|
|
70
|
+
msg.force_encoding('UTF-8')
|
|
71
|
+
@frame.class.new(version: @frame.version, type: :text, data: msg, decoded: true)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Frame
|
|
5
|
+
module Handler
|
|
6
|
+
autoload :Base, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/handler/base"
|
|
7
|
+
|
|
8
|
+
autoload :Handler03, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/handler/handler03"
|
|
9
|
+
autoload :Handler04, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/handler/handler04"
|
|
10
|
+
autoload :Handler05, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/handler/handler05"
|
|
11
|
+
autoload :Handler07, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/handler/handler07"
|
|
12
|
+
autoload :Handler75, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/handler/handler75"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Frame
|
|
5
|
+
class Incoming
|
|
6
|
+
class Client < Incoming
|
|
7
|
+
def incoming_masking?
|
|
8
|
+
false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def outgoing_masking?
|
|
12
|
+
@handler.masking?
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Frame
|
|
5
|
+
class Incoming
|
|
6
|
+
class Server < Incoming
|
|
7
|
+
def incoming_masking?
|
|
8
|
+
@handler.masking?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def outgoing_masking?
|
|
12
|
+
false
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/incoming.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Frame
|
|
5
|
+
# Construct or parse incoming WebSocket Frame.
|
|
6
|
+
# @note You should NEVER use this class directly - use Client or Server subclasses instead, as they contain additional frame options(i.e. Client-side masking in draft 04)
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# frame = NewRelic::Security::WebSocket::Frame::Incoming::Server.new(version: @handshake.version)
|
|
10
|
+
# frame << "\x81\x05\x48\x65\x6c\x6c\x6f\x81\x06\x77\x6f\x72\x6c\x64\x21"
|
|
11
|
+
# frame.next # "Hello"
|
|
12
|
+
# frame.next # "world!""
|
|
13
|
+
class Incoming < Base
|
|
14
|
+
autoload :Client, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/incoming/client"
|
|
15
|
+
autoload :Server, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/incoming/server"
|
|
16
|
+
|
|
17
|
+
def initialize(args = {})
|
|
18
|
+
@decoded = args[:decoded] || false
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# If data is still encoded after receiving then this is false. After calling "next" you will receive
|
|
23
|
+
# another instance of incoming frame, but with data decoded - this function will return true and
|
|
24
|
+
# to_s will return frame content instead of raw data.
|
|
25
|
+
# @return [Boolean] If frame already decoded?
|
|
26
|
+
def decoded?
|
|
27
|
+
@decoded
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Add provided string as raw incoming frame.
|
|
31
|
+
# @param data [String] Raw frame
|
|
32
|
+
def <<(data)
|
|
33
|
+
@data << data
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Return next complete frame.
|
|
37
|
+
# This function will merge together splitted frames and return as combined content.
|
|
38
|
+
# Check #error if nil received to check for eventual parsing errors
|
|
39
|
+
# @return [NewRelic::Security::WebSocket::Frame::Incoming] Single incoming frame or nil if no complete frame is available.
|
|
40
|
+
def next
|
|
41
|
+
@handler.decode_frame unless decoded?
|
|
42
|
+
end
|
|
43
|
+
rescue_method :next
|
|
44
|
+
|
|
45
|
+
# If decoded then this will return frame content. Otherwise it will return raw frame.
|
|
46
|
+
# @return [String] Data of frame
|
|
47
|
+
def to_s
|
|
48
|
+
@data
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Frame
|
|
5
|
+
class Outgoing
|
|
6
|
+
class Client < Outgoing
|
|
7
|
+
def incoming_masking?
|
|
8
|
+
false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def outgoing_masking?
|
|
12
|
+
@handler.masking?
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Frame
|
|
5
|
+
class Outgoing
|
|
6
|
+
class Server < Outgoing
|
|
7
|
+
def incoming_masking?
|
|
8
|
+
@handler.masking?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def outgoing_masking?
|
|
12
|
+
false
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/outgoing.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Frame
|
|
5
|
+
# Construct or parse outgoing WebSocket Frame.
|
|
6
|
+
# @note You should NEVER use this class directly - use Client or Server subclasses instead, as they contain additional frame options(i.e. Client-side masking in draft 04)
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# frame = NewRelic::Security::WebSocket::Frame::Outgoing::Server.new(version: @handshake.version, data: "Hello", type: :text)
|
|
10
|
+
# frame.to_s # "\x81\x05\x48\x65\x6c\x6c\x6f"
|
|
11
|
+
class Outgoing < Base
|
|
12
|
+
autoload :Client, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/outgoing/client"
|
|
13
|
+
autoload :Server, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/outgoing/server"
|
|
14
|
+
|
|
15
|
+
# Is selected type supported by current draft version?
|
|
16
|
+
# @return [Boolean] true if frame type is supported
|
|
17
|
+
def supported?
|
|
18
|
+
support_type?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Should current frame be sent? Exclude empty frames etc.
|
|
22
|
+
# @return [Boolean] true if frame should be sent
|
|
23
|
+
def require_sending?
|
|
24
|
+
!error?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Return raw frame formatted for sending.
|
|
28
|
+
def to_s
|
|
29
|
+
raise NewRelic::Security::WebSocket::Error::Frame::UnknownFrameType unless supported?
|
|
30
|
+
@handler.encode_frame
|
|
31
|
+
end
|
|
32
|
+
rescue_method :to_s
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Frame
|
|
5
|
+
autoload :Base, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/base"
|
|
6
|
+
autoload :Data, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/data"
|
|
7
|
+
autoload :Handler, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/handler"
|
|
8
|
+
autoload :Incoming, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/incoming"
|
|
9
|
+
autoload :Outgoing, "#{NewRelic::Security::WebSocket::ROOT}/websocket/frame/outgoing"
|
|
10
|
+
end
|
|
11
|
+
end
|
data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/base.rb
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Handshake
|
|
5
|
+
# @abstract Subclass and override to implement custom handshakes
|
|
6
|
+
class Base
|
|
7
|
+
include ExceptionHandler
|
|
8
|
+
include NiceInspect
|
|
9
|
+
|
|
10
|
+
attr_reader :host, :path, :query,
|
|
11
|
+
:state, :version, :secure,
|
|
12
|
+
:headers, :protocols
|
|
13
|
+
|
|
14
|
+
# Initialize new WebSocket Handshake and set it's state to :new
|
|
15
|
+
def initialize(args = {})
|
|
16
|
+
args.each do |k, v|
|
|
17
|
+
value = begin
|
|
18
|
+
v.dup
|
|
19
|
+
rescue TypeError
|
|
20
|
+
v
|
|
21
|
+
end
|
|
22
|
+
instance_variable_set("@#{k}", value)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
@state = :new
|
|
26
|
+
@handler = nil
|
|
27
|
+
|
|
28
|
+
@data = String.new('')
|
|
29
|
+
@headers ||= {}
|
|
30
|
+
@protocols ||= []
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @abstract Add data to handshake
|
|
34
|
+
def <<(data)
|
|
35
|
+
@data << data
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Return textual representation of handshake request or response
|
|
39
|
+
# @return [String] text of response
|
|
40
|
+
def to_s
|
|
41
|
+
@handler ? @handler.to_s : ''
|
|
42
|
+
end
|
|
43
|
+
rescue_method :to_s, return: ''
|
|
44
|
+
|
|
45
|
+
# Is parsing of data finished?
|
|
46
|
+
# @return [Boolena] True if request was completely parsed or error occured. False otherwise
|
|
47
|
+
def finished?
|
|
48
|
+
@state == :finished || @state == :error
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Is parsed data valid?
|
|
52
|
+
# @return [Boolean] False if some errors occured. Reason for error could be found in error method
|
|
53
|
+
def valid?
|
|
54
|
+
finished? && @error.nil? && @handler && @handler.valid?
|
|
55
|
+
end
|
|
56
|
+
rescue_method :valid?, return: false
|
|
57
|
+
|
|
58
|
+
# @abstract Should send data after parsing is finished?
|
|
59
|
+
def should_respond?
|
|
60
|
+
raise NotImplementedError
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Data left from parsing. Sometimes data that doesn't belong to handshake are added - use this method to retrieve them.
|
|
64
|
+
# @return [String] String if some data are available. Nil otherwise
|
|
65
|
+
def leftovers
|
|
66
|
+
(@leftovers.to_s.split("\n", reserved_leftover_lines + 1)[reserved_leftover_lines] || '').strip
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Return default port for protocol (80 for ws, 443 for wss)
|
|
70
|
+
def default_port
|
|
71
|
+
secure ? 443 : 80
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Check if provided port is a default one
|
|
75
|
+
def default_port?
|
|
76
|
+
port == default_port
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def port
|
|
80
|
+
@port || default_port
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# URI of request.
|
|
84
|
+
# @return [String] Full URI with protocol
|
|
85
|
+
# @example
|
|
86
|
+
# @handshake.uri #=> "ws://example.com/path?query=true"
|
|
87
|
+
def uri
|
|
88
|
+
uri = String.new(secure ? 'wss://' : 'ws://')
|
|
89
|
+
uri << host
|
|
90
|
+
uri << ":#{port}" unless default_port?
|
|
91
|
+
uri << path
|
|
92
|
+
uri << "?#{query}" if query
|
|
93
|
+
uri
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
# Number of lines after header that should be handled as belonging to handshake. Any data after those lines will be handled as leftovers.
|
|
99
|
+
# @return [Integer] Number of lines
|
|
100
|
+
def reserved_leftover_lines
|
|
101
|
+
0
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Changes state to error and sets error message
|
|
105
|
+
# @param [String] message Error message to set
|
|
106
|
+
def error=(message)
|
|
107
|
+
@state = :error
|
|
108
|
+
super
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
HEADER = /^([^:]+):\s*(.+)$/
|
|
112
|
+
|
|
113
|
+
# Parse data imported to handshake and sets state to finished if necessary.
|
|
114
|
+
# @return [Boolean] True if finished parsing. False if not all data received yet.
|
|
115
|
+
def parse_data
|
|
116
|
+
header, @leftovers = @data.split("\r\n\r\n", 2)
|
|
117
|
+
return false unless @leftovers # The whole header has not been received yet.
|
|
118
|
+
|
|
119
|
+
lines = header.split("\r\n")
|
|
120
|
+
|
|
121
|
+
first_line = lines.shift
|
|
122
|
+
parse_first_line(first_line)
|
|
123
|
+
|
|
124
|
+
lines.each do |line|
|
|
125
|
+
h = HEADER.match(line)
|
|
126
|
+
next unless h # Skip any invalid headers
|
|
127
|
+
key = h[1].strip.downcase
|
|
128
|
+
val = h[2].strip
|
|
129
|
+
# If the header is already set and refers to the websocket protocol, append the new value
|
|
130
|
+
if @headers.key?(key) && key =~ /^(sec-)?websocket-protocol$/
|
|
131
|
+
@headers[key] << ", #{val}"
|
|
132
|
+
else
|
|
133
|
+
@headers[key] = val
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
@state = :finished
|
|
138
|
+
true
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/client.rb
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
5
|
+
module NewRelic::Security::WebSocket
|
|
6
|
+
module Handshake
|
|
7
|
+
# Construct or parse a client WebSocket handshake.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# @handshake = NewRelic::Security::WebSocket::Handshake::Client.new(url: 'ws://example.com')
|
|
11
|
+
#
|
|
12
|
+
# # Create request
|
|
13
|
+
# @handshake.to_s # GET /demo HTTP/1.1
|
|
14
|
+
# # Upgrade: websocket
|
|
15
|
+
# # Connection: Upgrade
|
|
16
|
+
# # Host: example.com
|
|
17
|
+
# # Origin: http://example.com
|
|
18
|
+
# # Sec-WebSocket-Version: 13
|
|
19
|
+
# # Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
|
|
20
|
+
#
|
|
21
|
+
# # Parse server response
|
|
22
|
+
# @handshake << <<EOF
|
|
23
|
+
# HTTP/1.1 101 Switching Protocols\r
|
|
24
|
+
# Upgrade: websocket\r
|
|
25
|
+
# Connection: Upgrade\r
|
|
26
|
+
# Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r
|
|
27
|
+
# \r
|
|
28
|
+
# EOF
|
|
29
|
+
#
|
|
30
|
+
# # All data received?
|
|
31
|
+
# @handshake.finished?
|
|
32
|
+
#
|
|
33
|
+
# # No parsing errors?
|
|
34
|
+
# @handshake.valid?
|
|
35
|
+
#
|
|
36
|
+
class Client < Base
|
|
37
|
+
attr_reader :origin, :headers
|
|
38
|
+
|
|
39
|
+
# Initialize new WebSocket Client
|
|
40
|
+
#
|
|
41
|
+
# @param [Hash] args Arguments for client
|
|
42
|
+
#
|
|
43
|
+
# @option args [String] :host Host of request. Required if no :url param was provided.
|
|
44
|
+
# @option args [String] :origin Origin of request. Optional, should be used mostly by browsers. Default: nil
|
|
45
|
+
# @option args [String] :path Path of request. Should start with '/'. Default: '/'
|
|
46
|
+
# @option args [Integer] :port Port of request. Default: nil
|
|
47
|
+
# @option args [String] :query. Query for request. Should be in format "aaa=bbb&ccc=ddd"
|
|
48
|
+
# @option args [Boolean] :secure Defines protocol to use. If true then wss://, otherwise ws://. This option will not change default port - it should be handled by programmer.
|
|
49
|
+
# @option args [String] :url URL of request. Must by in format like ws://example.com/path?query=true. Every part of this url will be overriden by more specific arguments.
|
|
50
|
+
# @option args [String] :uri Alias to :url
|
|
51
|
+
# @option args [Array<String>] :protocols An array of supported sub-protocols
|
|
52
|
+
# @option args [Integer] :version Version of WebSocket to use. Default: 13 (this is version from RFC)
|
|
53
|
+
# @option args [Hash] :headers HTTP headers to use in the handshake
|
|
54
|
+
#
|
|
55
|
+
# @example
|
|
56
|
+
# Websocket::Handshake::Client.new(url: "ws://example.com/path?query=true")
|
|
57
|
+
def initialize(args = {})
|
|
58
|
+
super
|
|
59
|
+
|
|
60
|
+
if @url || @uri
|
|
61
|
+
uri = URI.parse(@url || @uri)
|
|
62
|
+
@secure ||= (uri.scheme == 'wss')
|
|
63
|
+
@host ||= uri.host
|
|
64
|
+
@port ||= uri.port || default_port
|
|
65
|
+
@path ||= uri.path
|
|
66
|
+
@query ||= uri.query
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
@path = '/' if @path.nil? || @path.empty?
|
|
70
|
+
@version ||= DEFAULT_VERSION
|
|
71
|
+
|
|
72
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::NoHostProvided unless @host
|
|
73
|
+
|
|
74
|
+
include_version
|
|
75
|
+
end
|
|
76
|
+
rescue_method :initialize
|
|
77
|
+
|
|
78
|
+
# Add text of response from Server. This method will parse content immediately and update state and error(if neccessary)
|
|
79
|
+
#
|
|
80
|
+
# @param [String] data Data to add
|
|
81
|
+
#
|
|
82
|
+
# @example
|
|
83
|
+
# @handshake << <<EOF
|
|
84
|
+
# HTTP/1.1 101 Switching Protocols
|
|
85
|
+
# Upgrade: websocket
|
|
86
|
+
# Connection: Upgrade
|
|
87
|
+
# Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
|
|
88
|
+
#
|
|
89
|
+
# EOF
|
|
90
|
+
def <<(data)
|
|
91
|
+
super
|
|
92
|
+
parse_data
|
|
93
|
+
end
|
|
94
|
+
rescue_method :<<
|
|
95
|
+
|
|
96
|
+
# Should send content to server after finished parsing?
|
|
97
|
+
# @return [Boolean] false
|
|
98
|
+
def should_respond?
|
|
99
|
+
false
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
# Include set of methods for selected protocol version
|
|
105
|
+
# @return [Boolean] false if protocol number is unknown, otherwise true
|
|
106
|
+
def include_version
|
|
107
|
+
@handler = case @version
|
|
108
|
+
when 75 then Handler::Client75.new(self)
|
|
109
|
+
when 76, 0 then Handler::Client76.new(self)
|
|
110
|
+
when 1..3 then Handler::Client01.new(self)
|
|
111
|
+
when 4..10 then Handler::Client04.new(self)
|
|
112
|
+
when 11..17 then Handler::Client11.new(self)
|
|
113
|
+
else raise NewRelic::Security::WebSocket::Error::Handshake::UnknownVersion
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
FIRST_LINE = %r{^HTTP\/1\.1 (\d{3})[\w\s]*$}
|
|
118
|
+
|
|
119
|
+
# Parse first line of Server response.
|
|
120
|
+
# @param [String] line Line to parse
|
|
121
|
+
# @return [Boolean] True if parsed correctly. False otherwise
|
|
122
|
+
def parse_first_line(line)
|
|
123
|
+
line_parts = line.match(FIRST_LINE)
|
|
124
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::InvalidHeader unless line_parts
|
|
125
|
+
status = line_parts[1]
|
|
126
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::InvalidStatusCode unless status == '101'
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Handshake
|
|
5
|
+
module Handler
|
|
6
|
+
# This class and it's descendants are included in client or server handshake in order to extend basic functionality
|
|
7
|
+
class Base
|
|
8
|
+
def initialize(handshake)
|
|
9
|
+
@handshake = handshake
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# @see NewRelic::Security::WebSocket::Handshake::Base#to_s
|
|
13
|
+
def to_s
|
|
14
|
+
result = [header_line]
|
|
15
|
+
handshake_keys.each do |key|
|
|
16
|
+
result << key.join(': ')
|
|
17
|
+
end
|
|
18
|
+
result << ''
|
|
19
|
+
result << finishing_line
|
|
20
|
+
result.join("\r\n")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def valid?
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
# Set first line of text representation according to specification.
|
|
30
|
+
# @return [String] First line of HTTP header
|
|
31
|
+
def header_line
|
|
32
|
+
''
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Set handshake headers. Provided as array because some protocol version require specific order of fields.
|
|
36
|
+
# @return [Array] List of headers as arrays [key, value]
|
|
37
|
+
def handshake_keys
|
|
38
|
+
[]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Set data to send after headers. In most cases it will be blank data.
|
|
42
|
+
# @return [String] data
|
|
43
|
+
def finishing_line
|
|
44
|
+
''
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Handshake
|
|
5
|
+
module Handler
|
|
6
|
+
class Client < Base
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#header_line
|
|
10
|
+
def header_line
|
|
11
|
+
path = @handshake.path
|
|
12
|
+
path += '?' + @handshake.query if @handshake.query
|
|
13
|
+
"GET #{path} HTTP/1.1"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#header_handshake_keys
|
|
17
|
+
def handshake_keys
|
|
18
|
+
super + @handshake.headers.to_a
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Verify if received header matches with one of the sent ones
|
|
22
|
+
# @return [Boolean] True if matching. False otherwise(appropriate error is set)
|
|
23
|
+
def verify_protocol
|
|
24
|
+
return true if supported_protocols.empty?
|
|
25
|
+
protos = provided_protocols & supported_protocols
|
|
26
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::UnsupportedProtocol if protos.empty?
|
|
27
|
+
true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'digest/md5'
|
|
4
|
+
|
|
5
|
+
module NewRelic::Security::WebSocket
|
|
6
|
+
module Handshake
|
|
7
|
+
module Handler
|
|
8
|
+
class Client01 < Client76
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#handshake_keys
|
|
12
|
+
def handshake_keys
|
|
13
|
+
keys = super
|
|
14
|
+
keys << ['Sec-WebSocket-Draft', @handshake.version]
|
|
15
|
+
keys
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|