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,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'digest/sha1'
|
|
4
|
+
require 'base64'
|
|
5
|
+
|
|
6
|
+
module NewRelic::Security::WebSocket
|
|
7
|
+
module Handshake
|
|
8
|
+
module Handler
|
|
9
|
+
class Client04 < Client
|
|
10
|
+
# @see NewRelic::Security::WebSocket::Handshake::Base#valid?
|
|
11
|
+
def valid?
|
|
12
|
+
super && verify_accept && verify_protocol
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#handshake_keys
|
|
18
|
+
def handshake_keys
|
|
19
|
+
keys = [
|
|
20
|
+
%w[Upgrade websocket],
|
|
21
|
+
%w[Connection Upgrade]
|
|
22
|
+
]
|
|
23
|
+
host = @handshake.host
|
|
24
|
+
host += ":#{@handshake.port}" unless @handshake.default_port?
|
|
25
|
+
keys << ['Host', host]
|
|
26
|
+
keys += super
|
|
27
|
+
keys << ['Sec-WebSocket-Origin', @handshake.origin] if @handshake.origin
|
|
28
|
+
keys << ['Sec-WebSocket-Version', @handshake.version]
|
|
29
|
+
keys << ['Sec-WebSocket-Key', key]
|
|
30
|
+
keys << ['Sec-WebSocket-Protocol', @handshake.protocols.join(', ')] if @handshake.protocols.any?
|
|
31
|
+
keys
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Sec-WebSocket-Key value
|
|
35
|
+
# @return [String] key
|
|
36
|
+
def key
|
|
37
|
+
@key ||= Base64.encode64((1..16).map { rand(255).chr } * '').strip
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Value of Sec-WebSocket-Accept that should be delivered back by server
|
|
41
|
+
# @return [Sering] accept
|
|
42
|
+
def accept
|
|
43
|
+
@accept ||= Base64.encode64(Digest::SHA1.digest(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')).strip
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Verify if received header Sec-WebSocket-Accept matches generated one.
|
|
47
|
+
# @return [Boolean] True if accept is matching. False otherwise(appropriate error is set)
|
|
48
|
+
def verify_accept
|
|
49
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::InvalidAuthentication unless @handshake.headers['sec-websocket-accept'] == accept
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def supported_protocols
|
|
54
|
+
@handshake.protocols
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def provided_protocols
|
|
58
|
+
@handshake.headers['sec-websocket-protocol'].to_s.split(/ *, */)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Handshake
|
|
5
|
+
module Handler
|
|
6
|
+
class Client11 < Client04
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#handshake_keys
|
|
10
|
+
def handshake_keys
|
|
11
|
+
super.collect do |key_pair|
|
|
12
|
+
if key_pair[0] == 'Sec-WebSocket-Origin'
|
|
13
|
+
['Origin', key_pair[1]]
|
|
14
|
+
else
|
|
15
|
+
key_pair
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Handshake
|
|
5
|
+
module Handler
|
|
6
|
+
class Client75 < Client
|
|
7
|
+
# @see NewRelic::Security::WebSocket::Handshake::Base#valid?
|
|
8
|
+
def valid?
|
|
9
|
+
super && verify_protocol
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#handshake_keys
|
|
15
|
+
def handshake_keys
|
|
16
|
+
keys = [
|
|
17
|
+
%w[Upgrade WebSocket],
|
|
18
|
+
%w[Connection Upgrade]
|
|
19
|
+
]
|
|
20
|
+
host = @handshake.host
|
|
21
|
+
host += ":#{@handshake.port}" unless @handshake.default_port?
|
|
22
|
+
keys << ['Host', host]
|
|
23
|
+
keys << ['Origin', @handshake.origin] if @handshake.origin
|
|
24
|
+
keys << ['WebSocket-Protocol', @handshake.protocols.first] if @handshake.protocols.any?
|
|
25
|
+
keys += super
|
|
26
|
+
keys
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def supported_protocols
|
|
30
|
+
Array(@handshake.protocols.first)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def provided_protocols
|
|
34
|
+
Array(@handshake.headers['websocket-protocol'].to_s.strip)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'digest/md5'
|
|
4
|
+
|
|
5
|
+
module NewRelic::Security::WebSocket
|
|
6
|
+
module Handshake
|
|
7
|
+
module Handler
|
|
8
|
+
class Client76 < Client75
|
|
9
|
+
# @see NewRelic::Security::WebSocket::Handshake::Base#valid?
|
|
10
|
+
def valid?
|
|
11
|
+
super && verify_challenge && verify_protocol
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
# @see NewRelic::Security::WebSocket::Handshake::Base#reserved_leftover_lines
|
|
17
|
+
def reserved_leftover_lines
|
|
18
|
+
1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#handshake_keys
|
|
22
|
+
def handshake_keys
|
|
23
|
+
keys = super
|
|
24
|
+
keys << ['Sec-WebSocket-Key1', key1]
|
|
25
|
+
keys << ['Sec-WebSocket-Key2', key2]
|
|
26
|
+
keys
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#finishing_line
|
|
30
|
+
def finishing_line
|
|
31
|
+
key3
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Sec-WebSocket-Key1 value
|
|
35
|
+
# @return [String] key
|
|
36
|
+
def key1
|
|
37
|
+
@key1 ||= generate_key(:key1)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Sec-WebSocket-Key2 value
|
|
41
|
+
# @return [String] key
|
|
42
|
+
def key2
|
|
43
|
+
@key2 ||= generate_key(:key2)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Value of third key, sent in body
|
|
47
|
+
# @return [String] key
|
|
48
|
+
def key3
|
|
49
|
+
@key3 ||= generate_key3
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Expected challenge that should be sent by server
|
|
53
|
+
# @return [String] challenge
|
|
54
|
+
def challenge
|
|
55
|
+
return @challenge if defined?(@challenge)
|
|
56
|
+
key1 && key2
|
|
57
|
+
sum = [@key1_number].pack('N*') +
|
|
58
|
+
[@key2_number].pack('N*') +
|
|
59
|
+
key3
|
|
60
|
+
|
|
61
|
+
@challenge = Digest::MD5.digest(sum).strip
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Verify if challenge sent by server match generated one
|
|
65
|
+
# @return [Boolena] True if challenge matches, false otherwise(sets appropriate error)
|
|
66
|
+
def verify_challenge
|
|
67
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::InvalidAuthentication unless @handshake.leftovers == challenge
|
|
68
|
+
true
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
NOISE_CHARS = ("\x21".."\x2f").to_a + ("\x3a".."\x7e").to_a
|
|
72
|
+
|
|
73
|
+
# Generate Sec-WebSocket-Key1 and Sec-WebSocket-Key2
|
|
74
|
+
# @param key [String] name of key. Will be used to set number variable needed later. Valid values: key1, key2
|
|
75
|
+
# @return [String] generated key
|
|
76
|
+
def generate_key(key)
|
|
77
|
+
spaces = rand(1..12)
|
|
78
|
+
max = 0xffffffff / spaces
|
|
79
|
+
number = rand(max + 1)
|
|
80
|
+
instance_variable_set("@#{key}_number", number)
|
|
81
|
+
key = (number * spaces).to_s
|
|
82
|
+
rand(1..12).times do
|
|
83
|
+
char = NOISE_CHARS[rand(NOISE_CHARS.size)]
|
|
84
|
+
pos = rand(key.size + 1)
|
|
85
|
+
key[pos...pos] = char
|
|
86
|
+
end
|
|
87
|
+
spaces.times do
|
|
88
|
+
pos = 1 + rand(key.size - 1)
|
|
89
|
+
key[pos...pos] = ' '
|
|
90
|
+
end
|
|
91
|
+
key
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Generate third key
|
|
95
|
+
def generate_key3
|
|
96
|
+
[rand(0x100000000)].pack('N') + [rand(0x100000000)].pack('N')
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def provided_protocols
|
|
100
|
+
Array(@handshake.headers['sec-websocket-protocol'].to_s.strip)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'digest/sha1'
|
|
4
|
+
require 'base64'
|
|
5
|
+
|
|
6
|
+
module NewRelic::Security::WebSocket
|
|
7
|
+
module Handshake
|
|
8
|
+
module Handler
|
|
9
|
+
class Server04 < Server
|
|
10
|
+
# @see NewRelic::Security::WebSocket::Handshake::Base#valid?
|
|
11
|
+
def valid?
|
|
12
|
+
super && verify_key
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#header_line
|
|
18
|
+
def header_line
|
|
19
|
+
'HTTP/1.1 101 Switching Protocols'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#handshake_keys
|
|
23
|
+
def handshake_keys
|
|
24
|
+
[
|
|
25
|
+
%w[Upgrade websocket],
|
|
26
|
+
%w[Connection Upgrade],
|
|
27
|
+
['Sec-WebSocket-Accept', signature]
|
|
28
|
+
] + protocol
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Signature of response, created from client request Sec-WebSocket-Key
|
|
32
|
+
# @return [String] signature
|
|
33
|
+
def signature
|
|
34
|
+
return unless key
|
|
35
|
+
string_to_sign = "#{key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
|
36
|
+
Base64.encode64(Digest::SHA1.digest(string_to_sign)).chomp
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def verify_key
|
|
40
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::InvalidAuthentication unless key
|
|
41
|
+
true
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def key
|
|
45
|
+
@handshake.headers['sec-websocket-key']
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def protocol
|
|
49
|
+
return [] unless @handshake.headers.key?('sec-websocket-protocol')
|
|
50
|
+
protos = @handshake.headers['sec-websocket-protocol'].split(/ *, */) & @handshake.protocols
|
|
51
|
+
[['Sec-WebSocket-Protocol', protos.first]]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Handshake
|
|
5
|
+
module Handler
|
|
6
|
+
class Server75 < Server
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def headers
|
|
10
|
+
{
|
|
11
|
+
origin: 'WebSocket-Origin',
|
|
12
|
+
location: 'WebSocket-Location',
|
|
13
|
+
protocol: 'WebSocket-Protocol'
|
|
14
|
+
}.freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#header_line
|
|
18
|
+
def header_line
|
|
19
|
+
'HTTP/1.1 101 Web Socket Protocol Handshake'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#handshake_keys
|
|
23
|
+
def handshake_keys
|
|
24
|
+
[
|
|
25
|
+
%w[Upgrade WebSocket],
|
|
26
|
+
%w[Connection Upgrade],
|
|
27
|
+
[headers[:origin], @handshake.headers['origin']],
|
|
28
|
+
[headers[:location], @handshake.uri]
|
|
29
|
+
] + protocol
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def protocol
|
|
33
|
+
return [] unless @handshake.headers.key?(headers[:protocol].downcase)
|
|
34
|
+
proto = @handshake.headers[headers[:protocol].downcase]
|
|
35
|
+
[[headers[:protocol], @handshake.protocols.include?(proto) ? proto : nil]]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'digest/md5'
|
|
4
|
+
|
|
5
|
+
module NewRelic::Security::WebSocket
|
|
6
|
+
module Handshake
|
|
7
|
+
module Handler
|
|
8
|
+
class Server76 < Server75
|
|
9
|
+
# @see NewRelic::Security::WebSocket::Handshake::Base#valid?
|
|
10
|
+
def valid?
|
|
11
|
+
super && !finishing_line.nil?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def headers
|
|
17
|
+
{
|
|
18
|
+
origin: 'Sec-WebSocket-Origin',
|
|
19
|
+
location: 'Sec-WebSocket-Location',
|
|
20
|
+
protocol: 'Sec-WebSocket-Protocol'
|
|
21
|
+
}.freeze
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @see NewRelic::Security::WebSocket::Handshake::Base#reserved_leftover_lines
|
|
25
|
+
def reserved_leftover_lines
|
|
26
|
+
1
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#header_line
|
|
30
|
+
def header_line
|
|
31
|
+
'HTTP/1.1 101 WebSocket Protocol Handshake'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @see NewRelic::Security::WebSocket::Handshake::Handler::Base#finishing_line
|
|
35
|
+
def finishing_line
|
|
36
|
+
@finishing_line ||= challenge_response
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Response to client challenge from request Sec-WebSocket-Key1, Sec-WebSocket-Key2 and leftovers
|
|
40
|
+
# @return [String] Challenge response or nil if error occured
|
|
41
|
+
def challenge_response
|
|
42
|
+
# Refer to 5.2 4-9 of the draft 76
|
|
43
|
+
first = numbers_over_spaces(@handshake.headers['sec-websocket-key1'].to_s)
|
|
44
|
+
second = numbers_over_spaces(@handshake.headers['sec-websocket-key2'].to_s)
|
|
45
|
+
third = @handshake.leftovers
|
|
46
|
+
|
|
47
|
+
sum = [first].pack('N*') +
|
|
48
|
+
[second].pack('N*') +
|
|
49
|
+
third
|
|
50
|
+
Digest::MD5.digest(sum)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Calculate numbers over spaces, according to spec 5.2
|
|
54
|
+
# @param [String] string Key to parse
|
|
55
|
+
# @return [Integer] Result of calculations or nil if error occured
|
|
56
|
+
def numbers_over_spaces(string)
|
|
57
|
+
numbers = string.scan(/[0-9]/).join.to_i
|
|
58
|
+
|
|
59
|
+
spaces = string.scan(/ /).size
|
|
60
|
+
# As per 5.2.5, abort the connection if spaces are zero.
|
|
61
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::InvalidAuthentication if spaces.zero?
|
|
62
|
+
|
|
63
|
+
# As per 5.2.6, abort if numbers is not an integral multiple of spaces
|
|
64
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::InvalidAuthentication if numbers % spaces != 0
|
|
65
|
+
|
|
66
|
+
quotient = numbers / spaces
|
|
67
|
+
|
|
68
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::InvalidAuthentication if quotient > 2**32 - 1
|
|
69
|
+
|
|
70
|
+
quotient
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Handshake
|
|
5
|
+
module Handler
|
|
6
|
+
autoload :Base, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/base"
|
|
7
|
+
|
|
8
|
+
autoload :Client, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/client"
|
|
9
|
+
autoload :Client01, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/client01"
|
|
10
|
+
autoload :Client04, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/client04"
|
|
11
|
+
autoload :Client11, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/client11"
|
|
12
|
+
autoload :Client75, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/client75"
|
|
13
|
+
autoload :Client76, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/client76"
|
|
14
|
+
|
|
15
|
+
autoload :Server, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/server"
|
|
16
|
+
autoload :Server04, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/server04"
|
|
17
|
+
autoload :Server75, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/server75"
|
|
18
|
+
autoload :Server76, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler/server76"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/server.rb
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Handshake
|
|
5
|
+
# Construct or parse a server WebSocket handshake.
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
# handshake = NewRelic::Security::WebSocket::Handshake::Server.new
|
|
9
|
+
#
|
|
10
|
+
# # Parse client request
|
|
11
|
+
# @handshake << <<EOF
|
|
12
|
+
# GET /demo HTTP/1.1\r
|
|
13
|
+
# Upgrade: websocket\r
|
|
14
|
+
# Connection: Upgrade\r
|
|
15
|
+
# Host: example.com\r
|
|
16
|
+
# Origin: http://example.com\r
|
|
17
|
+
# Sec-WebSocket-Version: 13\r
|
|
18
|
+
# Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r
|
|
19
|
+
# \r
|
|
20
|
+
# EOF
|
|
21
|
+
#
|
|
22
|
+
# # All data received?
|
|
23
|
+
# @handshake.finished?
|
|
24
|
+
#
|
|
25
|
+
# # No parsing errors?
|
|
26
|
+
# @handshake.valid?
|
|
27
|
+
#
|
|
28
|
+
# # Create response
|
|
29
|
+
# @handshake.to_s # HTTP/1.1 101 Switching Protocols
|
|
30
|
+
# # Upgrade: websocket
|
|
31
|
+
# # Connection: Upgrade
|
|
32
|
+
# # Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
|
|
33
|
+
#
|
|
34
|
+
class Server < Base
|
|
35
|
+
# Initialize new WebSocket Server
|
|
36
|
+
#
|
|
37
|
+
# @param [Hash] args Arguments for server
|
|
38
|
+
#
|
|
39
|
+
# @option args [Boolean] :secure If true then server will use wss:// protocol
|
|
40
|
+
# @option args [Array<String>] :protocols an array of supported sub-protocols
|
|
41
|
+
#
|
|
42
|
+
# @example
|
|
43
|
+
# Websocket::Handshake::Server.new(secure: true)
|
|
44
|
+
def initialize(args = {})
|
|
45
|
+
super
|
|
46
|
+
@secure ||= false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Add text of request from Client. This method will parse content immediately and update version, state and error(if neccessary)
|
|
50
|
+
#
|
|
51
|
+
# @param [String] data Data to add
|
|
52
|
+
#
|
|
53
|
+
# @example
|
|
54
|
+
# @handshake << <<EOF
|
|
55
|
+
# GET /demo HTTP/1.1
|
|
56
|
+
# Upgrade: websocket
|
|
57
|
+
# Connection: Upgrade
|
|
58
|
+
# Host: example.com
|
|
59
|
+
# Origin: http://example.com
|
|
60
|
+
# Sec-WebSocket-Version: 13
|
|
61
|
+
# Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
|
|
62
|
+
#
|
|
63
|
+
# EOF
|
|
64
|
+
def <<(data)
|
|
65
|
+
super
|
|
66
|
+
set_version if parse_data
|
|
67
|
+
end
|
|
68
|
+
rescue_method :<<
|
|
69
|
+
|
|
70
|
+
# Parse the request from a rack environment
|
|
71
|
+
# @param env Rack Environment
|
|
72
|
+
#
|
|
73
|
+
# @example
|
|
74
|
+
# @handshake.from_rack(env)
|
|
75
|
+
def from_rack(env)
|
|
76
|
+
@headers = env.select { |key, _value| key.to_s.start_with? 'HTTP_' }.each_with_object({}) do |tuple, memo|
|
|
77
|
+
key, value = tuple
|
|
78
|
+
memo[key.gsub(/\AHTTP_/, '').tr('_', '-').downcase] = value
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
@path = env['REQUEST_PATH']
|
|
82
|
+
@query = env['QUERY_STRING']
|
|
83
|
+
|
|
84
|
+
set_version
|
|
85
|
+
|
|
86
|
+
# Passenger is blocking on read
|
|
87
|
+
# Unicorn doesn't support readpartial
|
|
88
|
+
# Maybe someone is providing even plain string?
|
|
89
|
+
# Better safe than sorry...
|
|
90
|
+
if @version == 76
|
|
91
|
+
input = env['rack.input']
|
|
92
|
+
@leftovers = if input.respond_to?(:readpartial)
|
|
93
|
+
input.readpartial
|
|
94
|
+
elsif input.respond_to?(:read)
|
|
95
|
+
input.read
|
|
96
|
+
else
|
|
97
|
+
input.to_s
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
@state = :finished
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Parse the request from hash
|
|
105
|
+
# @param hash Hash to import data
|
|
106
|
+
# @option hash [Hash] :headers HTTP headers of request, downcased
|
|
107
|
+
# @option hash [String] :path Path for request(without host and query string)
|
|
108
|
+
# @option hash [String] :query Query string for request
|
|
109
|
+
# @option hash [String] :body Body of request(if exists)
|
|
110
|
+
#
|
|
111
|
+
# @example
|
|
112
|
+
# @handshake.from_hash(hash)
|
|
113
|
+
def from_hash(hash)
|
|
114
|
+
@headers = hash[:headers] || {}
|
|
115
|
+
@path = hash[:path] || '/'
|
|
116
|
+
@query = hash[:query] || ''
|
|
117
|
+
@leftovers = hash[:body]
|
|
118
|
+
|
|
119
|
+
set_version
|
|
120
|
+
@state = :finished
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Should send content to client after finished parsing?
|
|
124
|
+
# @return [Boolean] true
|
|
125
|
+
def should_respond?
|
|
126
|
+
true
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Host of server according to client header
|
|
130
|
+
# @return [String] host
|
|
131
|
+
def host
|
|
132
|
+
@host || @headers['host'].to_s.split(':')[0].to_s
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Port of server according to client header
|
|
136
|
+
# @return [Integer] port
|
|
137
|
+
def port
|
|
138
|
+
(@port || @headers['host'].to_s.split(':')[1] || default_port).to_i
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
private
|
|
142
|
+
|
|
143
|
+
# Set version of protocol basing on client requets. AFter cotting method calls include_version.
|
|
144
|
+
def set_version
|
|
145
|
+
@version = @headers['sec-websocket-version'].to_i if @headers['sec-websocket-version']
|
|
146
|
+
@version ||= @headers['sec-websocket-draft'].to_i if @headers['sec-websocket-draft']
|
|
147
|
+
@version ||= 76 if @headers['sec-websocket-key1']
|
|
148
|
+
@version ||= 75
|
|
149
|
+
include_version
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Include set of methods for selected protocol version
|
|
153
|
+
# @return [Boolean] false if protocol number is unknown, otherwise true
|
|
154
|
+
def include_version
|
|
155
|
+
@handler = case @version
|
|
156
|
+
when 75 then Handler::Server75.new(self)
|
|
157
|
+
when 76, 0..3 then Handler::Server76.new(self)
|
|
158
|
+
when 4..17 then Handler::Server04.new(self)
|
|
159
|
+
else raise NewRelic::Security::WebSocket::Error::Handshake::UnknownVersion
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
PATH = %r{^(\w+) (\/[^\s]*) HTTP\/1\.1$}
|
|
164
|
+
|
|
165
|
+
# Parse first line of Client response.
|
|
166
|
+
# @param [String] line Line to parse
|
|
167
|
+
# @return [Boolean] True if parsed correctly. False otherwise
|
|
168
|
+
def parse_first_line(line)
|
|
169
|
+
line_parts = line.match(PATH)
|
|
170
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::InvalidHeader unless line_parts
|
|
171
|
+
method = line_parts[1].strip
|
|
172
|
+
raise NewRelic::Security::WebSocket::Error::Handshake::GetRequestRequired unless method == 'GET'
|
|
173
|
+
|
|
174
|
+
resource_name = line_parts[2].strip
|
|
175
|
+
@path, @query = resource_name.split('?', 2)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module Handshake
|
|
5
|
+
autoload :Base, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/base"
|
|
6
|
+
autoload :Client, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/client"
|
|
7
|
+
autoload :Handler, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/handler"
|
|
8
|
+
autoload :Server, "#{NewRelic::Security::WebSocket::ROOT}/websocket/handshake/server"
|
|
9
|
+
end
|
|
10
|
+
end
|
data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/nice_inspect.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NewRelic::Security::WebSocket
|
|
4
|
+
module NiceInspect
|
|
5
|
+
# Recreate inspect as #to_s will be overwritten
|
|
6
|
+
def inspect
|
|
7
|
+
vars = instance_variables.map { |v| "#{v}=#{instance_variable_get(v).inspect}" }.join(', ')
|
|
8
|
+
insp = Kernel.format("#{self.class}:0x%08x", __id__)
|
|
9
|
+
"<#{insp} #{vars}>"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|