ruby_smb 1.0.3 → 2.0.1
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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.travis.yml +3 -2
- data/Gemfile +6 -2
- data/README.md +35 -47
- data/examples/enum_registry_key.rb +28 -0
- data/examples/enum_registry_values.rb +30 -0
- data/examples/negotiate.rb +51 -8
- data/examples/pipes.rb +2 -1
- data/examples/read_file_encryption.rb +56 -0
- data/examples/read_registry_key_value.rb +32 -0
- data/lib/ruby_smb.rb +4 -1
- data/lib/ruby_smb/client.rb +233 -22
- data/lib/ruby_smb/client/authentication.rb +70 -33
- data/lib/ruby_smb/client/echo.rb +20 -2
- data/lib/ruby_smb/client/encryption.rb +62 -0
- data/lib/ruby_smb/client/negotiation.rb +172 -24
- data/lib/ruby_smb/client/signing.rb +19 -0
- data/lib/ruby_smb/client/tree_connect.rb +24 -18
- data/lib/ruby_smb/client/utils.rb +8 -7
- data/lib/ruby_smb/client/winreg.rb +46 -0
- data/lib/ruby_smb/crypto.rb +30 -0
- data/lib/ruby_smb/dcerpc.rb +38 -0
- data/lib/ruby_smb/dcerpc/bind.rb +2 -2
- data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
- data/lib/ruby_smb/dcerpc/error.rb +3 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
- data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
- data/lib/ruby_smb/dcerpc/request.rb +28 -9
- data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
- data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
- data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
- data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
- data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
- data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
- data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
- data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
- data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
- data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
- data/lib/ruby_smb/dispatcher/socket.rb +4 -3
- data/lib/ruby_smb/error.rb +68 -2
- data/lib/ruby_smb/generic_packet.rb +33 -4
- data/lib/ruby_smb/smb1/commands.rb +1 -1
- data/lib/ruby_smb/smb1/file.rb +66 -15
- data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/empty_packet.rb +10 -1
- data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
- data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
- data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/write_andx_request.rb +3 -6
- data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/pipe.rb +87 -6
- data/lib/ruby_smb/smb1/tree.rb +50 -3
- data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
- data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
- data/lib/ruby_smb/smb2/file.rb +103 -25
- data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
- data/lib/ruby_smb/smb2/packet.rb +2 -0
- data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
- data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -3
- data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -17
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +52 -5
- data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
- data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +93 -10
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +10 -22
- data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
- data/lib/ruby_smb/smb2/pipe.rb +86 -12
- data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
- data/lib/ruby_smb/smb2/tree.rb +65 -21
- data/lib/ruby_smb/version.rb +1 -1
- data/ruby_smb.gemspec +5 -3
- data/spec/lib/ruby_smb/client_spec.rb +1612 -108
- data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
- data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
- data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
- data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
- data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +2 -2
- data/spec/lib/ruby_smb/error_spec.rb +59 -0
- data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
- data/spec/lib/ruby_smb/smb1/file_spec.rb +191 -2
- data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +68 -0
- data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
- data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +272 -149
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
- data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
- data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +323 -6
- data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
- data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
- data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
- data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
- data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
- data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
- data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -22
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +286 -149
- data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +261 -2
- metadata +191 -83
- metadata.gz.sig +0 -0
- data/lib/ruby_smb/smb1/dcerpc.rb +0 -67
- data/lib/ruby_smb/smb2/dcerpc.rb +0 -70
- data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +0 -37
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# This example script is used for testing the Winreg registry key value read functionality.
|
4
|
+
# It will attempt to connect to a host and reads the value of a specified registry key.
|
5
|
+
# Example usage: ruby enum_registry_key.rb 192.168.172.138 msfadmin msfadmin HKLM\\My\\Key ValueName
|
6
|
+
# This will try to connect to \\192.168.172.138 with the msfadmin:msfadmin credentialas and reads the ValueName data corresponding to the HKLM\\My\\Key registry key.
|
7
|
+
|
8
|
+
require 'bundler/setup'
|
9
|
+
require 'ruby_smb'
|
10
|
+
|
11
|
+
address = ARGV[0]
|
12
|
+
username = ARGV[1]
|
13
|
+
password = ARGV[2]
|
14
|
+
registry_key = ARGV[3]
|
15
|
+
value_name = ARGV[4]
|
16
|
+
|
17
|
+
sock = TCPSocket.new address, 445
|
18
|
+
dispatcher = RubySMB::Dispatcher::Socket.new(sock, read_timeout: 60)
|
19
|
+
|
20
|
+
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: true, username: username, password: password)
|
21
|
+
protocol = client.negotiate
|
22
|
+
status = client.authenticate
|
23
|
+
|
24
|
+
puts "#{protocol}: #{status}"
|
25
|
+
puts "Key: #{registry_key}"
|
26
|
+
puts "Value: #{value_name}"
|
27
|
+
|
28
|
+
key_value = client.read_registry_key_value(address, registry_key, value_name)
|
29
|
+
puts key_value
|
30
|
+
|
31
|
+
client.disconnect!
|
32
|
+
|
data/lib/ruby_smb.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'bindata'
|
2
2
|
require 'net/ntlm'
|
3
3
|
require 'net/ntlm/client'
|
4
|
+
require 'openssl'
|
5
|
+
require 'openssl/ccm'
|
6
|
+
require 'openssl/cmac'
|
4
7
|
require 'windows_error'
|
5
8
|
require 'windows_error/nt_status'
|
6
9
|
# A packet parsing and manipulation library for the SMB1 and SMB2 protocols
|
@@ -15,7 +18,6 @@ module RubySMB
|
|
15
18
|
require 'ruby_smb/field'
|
16
19
|
require 'ruby_smb/nbss'
|
17
20
|
require 'ruby_smb/fscc'
|
18
|
-
require 'ruby_smb/dcerpc'
|
19
21
|
require 'ruby_smb/generic_packet'
|
20
22
|
require 'ruby_smb/dispatcher'
|
21
23
|
require 'ruby_smb/version'
|
@@ -23,4 +25,5 @@ module RubySMB
|
|
23
25
|
require 'ruby_smb/smb2'
|
24
26
|
require 'ruby_smb/smb1'
|
25
27
|
require 'ruby_smb/client'
|
28
|
+
require 'ruby_smb/crypto'
|
26
29
|
end
|
data/lib/ruby_smb/client.rb
CHANGED
@@ -8,6 +8,8 @@ module RubySMB
|
|
8
8
|
require 'ruby_smb/client/tree_connect'
|
9
9
|
require 'ruby_smb/client/echo'
|
10
10
|
require 'ruby_smb/client/utils'
|
11
|
+
require 'ruby_smb/client/winreg'
|
12
|
+
require 'ruby_smb/client/encryption'
|
11
13
|
|
12
14
|
include RubySMB::Client::Negotiation
|
13
15
|
include RubySMB::Client::Authentication
|
@@ -15,13 +17,21 @@ module RubySMB
|
|
15
17
|
include RubySMB::Client::TreeConnect
|
16
18
|
include RubySMB::Client::Echo
|
17
19
|
include RubySMB::Client::Utils
|
20
|
+
include RubySMB::Client::Winreg
|
21
|
+
include RubySMB::Client::Encryption
|
18
22
|
|
19
23
|
# The Default SMB1 Dialect string used in an SMB1 Negotiate Request
|
20
24
|
SMB1_DIALECT_SMB1_DEFAULT = 'NT LM 0.12'.freeze
|
21
25
|
# The Default SMB2 Dialect string used in an SMB1 Negotiate Request
|
22
26
|
SMB1_DIALECT_SMB2_DEFAULT = 'SMB 2.002'.freeze
|
23
|
-
# Dialect
|
24
|
-
|
27
|
+
# The SMB2 wildcard revision number Dialect string used in an SMB1 Negotiate Request
|
28
|
+
# It indicates that the server implements SMB 2.1 or future dialect revisions
|
29
|
+
# Note that this must be used for SMB3
|
30
|
+
SMB1_DIALECT_SMB2_WILDCARD = 'SMB 2.???'.freeze
|
31
|
+
# Dialect values for SMB2
|
32
|
+
SMB2_DIALECT_DEFAULT = ['0x0202', '0x0210']
|
33
|
+
# Dialect values for SMB3
|
34
|
+
SMB3_DIALECT_DEFAULT = ['0x0300', '0x0302', '0x0311']
|
25
35
|
# The default maximum size of a SMB message that the Client accepts (in bytes)
|
26
36
|
MAX_BUFFER_SIZE = 64512
|
27
37
|
# The default maximum size of a SMB message that the Server accepts (in bytes)
|
@@ -133,6 +143,11 @@ module RubySMB
|
|
133
143
|
# @return [Boolean]
|
134
144
|
attr_accessor :smb2
|
135
145
|
|
146
|
+
# Whether or not the Client should support SMB3
|
147
|
+
# @!attribute [rw] smb3
|
148
|
+
# @return [Boolean]
|
149
|
+
attr_accessor :smb3
|
150
|
+
|
136
151
|
# Tracks the current SMB2 Message ID that keeps communication in sync
|
137
152
|
# @!attribute [rw] smb2_message_id
|
138
153
|
# @return [Integer]
|
@@ -176,12 +191,80 @@ module RubySMB
|
|
176
191
|
# @return [Integer]
|
177
192
|
attr_accessor :server_max_transact_size
|
178
193
|
|
194
|
+
# The algorithm to compute the preauthentication integrity hash (SMB 3.1.1).
|
195
|
+
# @!attribute [rw] preauth_integrity_hash_algorithm
|
196
|
+
# @return [String]
|
197
|
+
attr_accessor :preauth_integrity_hash_algorithm
|
198
|
+
|
199
|
+
# The preauthentication integrity hash value (SMB 3.1.1).
|
200
|
+
# @!attribute [rw] preauth_integrity_hash_value
|
201
|
+
# @return [String]
|
202
|
+
attr_accessor :preauth_integrity_hash_value
|
203
|
+
|
204
|
+
# The algorithm for encryption (SMB 3.x).
|
205
|
+
# @!attribute [rw] encryption_algorithm
|
206
|
+
# @return [String]
|
207
|
+
attr_accessor :encryption_algorithm
|
208
|
+
|
209
|
+
# The client encryption key (SMB 3.x).
|
210
|
+
# @!attribute [rw] client_encryption_key
|
211
|
+
# @return [String]
|
212
|
+
attr_accessor :client_encryption_key
|
213
|
+
|
214
|
+
# The server encryption key (SMB 3.x).
|
215
|
+
# @!attribute [rw] server_encryption_key
|
216
|
+
# @return [String]
|
217
|
+
attr_accessor :server_encryption_key
|
218
|
+
|
219
|
+
# Whether or not the whole session needs to be encrypted (SMB 3.x)
|
220
|
+
# @!attribute [rw] session_encrypt_data
|
221
|
+
# @return [Boolean]
|
222
|
+
attr_accessor :session_encrypt_data
|
223
|
+
|
224
|
+
# The encryption algorithms supported by the server (SMB 3.x).
|
225
|
+
# @!attribute [rw] server_encryption_algorithms
|
226
|
+
# @return [Array<Integer>] list of supported encryption algorithms
|
227
|
+
# (constants defined in RubySMB::SMB2::EncryptionCapabilities)
|
228
|
+
attr_accessor :server_encryption_algorithms
|
229
|
+
|
230
|
+
# The compression algorithms supported by the server (SMB 3.x).
|
231
|
+
# @!attribute [rw] server_compression_algorithms
|
232
|
+
# @return [Array<Integer>] list of supported compression algorithms
|
233
|
+
# (constants defined in RubySMB::SMB2::CompressionCapabilities)
|
234
|
+
attr_accessor :server_compression_algorithms
|
235
|
+
|
236
|
+
# The GUID of the server (SMB 2.x and 3.x).
|
237
|
+
# @!attribute [rw] server_guid
|
238
|
+
# @return [String]
|
239
|
+
attr_accessor :server_guid
|
240
|
+
|
241
|
+
# The server's start time if it is reported as part of the negotiation
|
242
|
+
# process (SMB 2.x and 3.x). This value is nil if the server does not report
|
243
|
+
# it (reports a value of 0).
|
244
|
+
# @!attribute [rw] server_start_time
|
245
|
+
# @return [Time] the time that the server reports that it was started at
|
246
|
+
attr_accessor :server_start_time
|
247
|
+
|
248
|
+
# The server's current time if it is reported as part of the negotiation
|
249
|
+
# process (SMB 2.x and 3.x). This value is nil if the server does not report
|
250
|
+
# it (reports a value of 0).
|
251
|
+
# @!attribute [rw] server_system_time
|
252
|
+
# @return [Time] the time that the server reports as current
|
253
|
+
attr_accessor :server_system_time
|
254
|
+
|
255
|
+
# The SMB version that has been successfully negotiated. This value is only
|
256
|
+
# set after the NEGOTIATE handshake has been performed.
|
257
|
+
# @!attribute [rw] negotiated_smb_version
|
258
|
+
# @return [Integer] the negotiated SMB version
|
259
|
+
attr_accessor :negotiated_smb_version
|
260
|
+
|
179
261
|
# @param dispatcher [RubySMB::Dispatcher::Socket] the packet dispatcher to use
|
180
262
|
# @param smb1 [Boolean] whether or not to enable SMB1 support
|
181
263
|
# @param smb2 [Boolean] whether or not to enable SMB2 support
|
182
|
-
|
264
|
+
# @param smb3 [Boolean] whether or not to enable SMB3 support
|
265
|
+
def initialize(dispatcher, smb1: true, smb2: true, smb3: true, username:, password:, domain: '.', local_workstation: 'WORKSTATION', always_encrypt: true)
|
183
266
|
raise ArgumentError, 'No Dispatcher provided' unless dispatcher.is_a? RubySMB::Dispatcher::Base
|
184
|
-
if smb1 == false && smb2 == false
|
267
|
+
if smb1 == false && smb2 == false && smb3 == false
|
185
268
|
raise ArgumentError, 'You must enable at least one Protocol'
|
186
269
|
end
|
187
270
|
@dispatcher = dispatcher
|
@@ -194,6 +277,7 @@ module RubySMB
|
|
194
277
|
@signing_required = false
|
195
278
|
@smb1 = smb1
|
196
279
|
@smb2 = smb2
|
280
|
+
@smb3 = smb3
|
197
281
|
@username = username.encode('utf-8') || ''.encode('utf-8')
|
198
282
|
@max_buffer_size = MAX_BUFFER_SIZE
|
199
283
|
# These sizes will be modifed during negotiation
|
@@ -202,10 +286,14 @@ module RubySMB
|
|
202
286
|
@server_max_write_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
|
203
287
|
@server_max_transact_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
|
204
288
|
|
289
|
+
# SMB 3.x options
|
290
|
+
@session_encrypt_data = always_encrypt
|
291
|
+
|
205
292
|
negotiate_version_flag = 0x02000000
|
206
293
|
flags = Net::NTLM::Client::DEFAULT_FLAGS |
|
207
294
|
Net::NTLM::FLAGS[:TARGET_INFO] |
|
208
|
-
negotiate_version_flag
|
295
|
+
negotiate_version_flag ^
|
296
|
+
Net::NTLM::FLAGS[:OEM]
|
209
297
|
|
210
298
|
@ntlm_client = Net::NTLM::Client.new(
|
211
299
|
@username,
|
@@ -241,7 +329,7 @@ module RubySMB
|
|
241
329
|
# @param data [String] the data the server should echo back (ignored in SMB2)
|
242
330
|
# @return [WindowsError::ErrorCode] the NTStatus of the last response received
|
243
331
|
def echo(count: 1, data: '')
|
244
|
-
response = if smb2
|
332
|
+
response = if smb2 || smb3
|
245
333
|
smb2_echo
|
246
334
|
else
|
247
335
|
smb1_echo(count: count, data: data)
|
@@ -256,10 +344,8 @@ module RubySMB
|
|
256
344
|
# @param packet [RubySMB::GenericPacket] the packet to set the message id for
|
257
345
|
# @return [RubySMB::GenericPacket] the modified packet
|
258
346
|
def increment_smb_message_id(packet)
|
259
|
-
|
260
|
-
|
261
|
-
self.smb2_message_id += 1
|
262
|
-
end
|
347
|
+
packet.smb2_header.message_id = smb2_message_id
|
348
|
+
self.smb2_message_id += 1
|
263
349
|
packet
|
264
350
|
end
|
265
351
|
|
@@ -281,7 +367,8 @@ module RubySMB
|
|
281
367
|
negotiate_version_flag = 0x02000000
|
282
368
|
flags = Net::NTLM::Client::DEFAULT_FLAGS |
|
283
369
|
Net::NTLM::FLAGS[:TARGET_INFO] |
|
284
|
-
negotiate_version_flag
|
370
|
+
negotiate_version_flag ^
|
371
|
+
Net::NTLM::FLAGS[:OEM]
|
285
372
|
|
286
373
|
@ntlm_client = Net::NTLM::Client.new(
|
287
374
|
@username,
|
@@ -297,15 +384,32 @@ module RubySMB
|
|
297
384
|
# Sends a LOGOFF command to the remote server to terminate the session
|
298
385
|
#
|
299
386
|
# @return [WindowsError::ErrorCode] the NTStatus of the response
|
387
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response packet is not a LogoffResponse packet
|
300
388
|
def logoff!
|
301
|
-
if smb2
|
389
|
+
if smb2 || smb3
|
302
390
|
request = RubySMB::SMB2::Packet::LogoffRequest.new
|
303
391
|
raw_response = send_recv(request)
|
304
392
|
response = RubySMB::SMB2::Packet::LogoffResponse.read(raw_response)
|
393
|
+
unless response.valid?
|
394
|
+
raise RubySMB::Error::InvalidPacket.new(
|
395
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
396
|
+
expected_cmd: RubySMB::SMB2::Packet::LogoffResponse::COMMAND,
|
397
|
+
received_proto: response.smb2_header.protocol,
|
398
|
+
received_cmd: response.smb2_header.command
|
399
|
+
)
|
400
|
+
end
|
305
401
|
else
|
306
402
|
request = RubySMB::SMB1::Packet::LogoffRequest.new
|
307
403
|
raw_response = send_recv(request)
|
308
404
|
response = RubySMB::SMB1::Packet::LogoffResponse.read(raw_response)
|
405
|
+
unless response.valid?
|
406
|
+
raise RubySMB::Error::InvalidPacket.new(
|
407
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
408
|
+
expected_cmd: RubySMB::SMB1::Packet::LogoffResponse::COMMAND,
|
409
|
+
received_proto: response.smb_header.protocol,
|
410
|
+
received_cmd: response.smb_header.command
|
411
|
+
)
|
412
|
+
end
|
309
413
|
end
|
310
414
|
wipe_state!
|
311
415
|
response.status_code
|
@@ -315,9 +419,13 @@ module RubySMB
|
|
315
419
|
# It will also sign the packet if neccessary.
|
316
420
|
#
|
317
421
|
# @param packet [RubySMB::GenericPacket] the request to be sent
|
422
|
+
# @param encrypt [Boolean] true if encryption has to be enabled for this transaction
|
423
|
+
# (note that if @session_encrypt_data is set, encryption will be enabled
|
424
|
+
# regardless of this parameter value)
|
318
425
|
# @return [String] the raw response data received
|
319
|
-
def send_recv(packet)
|
320
|
-
|
426
|
+
def send_recv(packet, encrypt: false)
|
427
|
+
version = packet.packet_smb_version
|
428
|
+
case version
|
321
429
|
when 'SMB1'
|
322
430
|
packet.smb_header.uid = user_id if user_id
|
323
431
|
packet = smb1_sign(packet)
|
@@ -325,25 +433,110 @@ module RubySMB
|
|
325
433
|
packet = increment_smb_message_id(packet)
|
326
434
|
packet.smb2_header.session_id = session_id
|
327
435
|
unless packet.is_a?(RubySMB::SMB2::Packet::SessionSetupRequest)
|
328
|
-
|
436
|
+
if self.smb2
|
437
|
+
packet = smb2_sign(packet)
|
438
|
+
elsif self.smb3
|
439
|
+
packet = smb3_sign(packet)
|
440
|
+
end
|
329
441
|
end
|
330
442
|
else
|
331
443
|
packet = packet
|
332
444
|
end
|
333
|
-
|
334
|
-
|
445
|
+
|
446
|
+
if can_be_encrypted?(packet) && encryption_supported? && (@session_encrypt_data || encrypt)
|
447
|
+
send_encrypt(packet)
|
448
|
+
raw_response = recv_encrypt
|
449
|
+
loop do
|
450
|
+
break unless is_status_pending?(raw_response)
|
451
|
+
sleep 1
|
452
|
+
raw_response = recv_encrypt
|
453
|
+
end
|
454
|
+
else
|
455
|
+
dispatcher.send_packet(packet)
|
456
|
+
raw_response = dispatcher.recv_packet
|
457
|
+
loop do
|
458
|
+
break unless is_status_pending?(raw_response)
|
459
|
+
sleep 1
|
460
|
+
raw_response = dispatcher.recv_packet
|
461
|
+
end unless version == 'SMB1'
|
462
|
+
end
|
335
463
|
|
336
464
|
self.sequence_counter += 1 if signing_required && !session_key.empty?
|
337
465
|
raw_response
|
338
466
|
end
|
339
467
|
|
468
|
+
# Check if the response is an asynchronous operation with STATUS_PENDING
|
469
|
+
# status code.
|
470
|
+
#
|
471
|
+
# @param raw_response [String] the raw response packet
|
472
|
+
# @return [Boolean] true if it is a status pending operation, false otherwise
|
473
|
+
def is_status_pending?(raw_response)
|
474
|
+
smb2_header = RubySMB::SMB2::SMB2Header.read(raw_response)
|
475
|
+
value = smb2_header.nt_status.value
|
476
|
+
status_code = WindowsError::NTStatus.find_by_retval(value).first
|
477
|
+
status_code == WindowsError::NTStatus::STATUS_PENDING &&
|
478
|
+
smb2_header.flags.async_command == 1
|
479
|
+
end
|
480
|
+
|
481
|
+
# Check if the request packet can be encrypted. Per the SMB2 spec,
|
482
|
+
# SessionSetupRequest and NegotiateRequest must not be encrypted.
|
483
|
+
#
|
484
|
+
# @param packet [RubySMB::GenericPacket] the request packet
|
485
|
+
# @return [Boolean] true if the packet can be encrypted
|
486
|
+
def can_be_encrypted?(packet)
|
487
|
+
return false if packet.packet_smb_version == 'SMB1'
|
488
|
+
[RubySMB::SMB2::Packet::SessionSetupRequest, RubySMB::SMB2::Packet::NegotiateRequest].none? do |klass|
|
489
|
+
packet.is_a?(klass)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
# Check if the current dialect supports encryption.
|
494
|
+
#
|
495
|
+
# @return [Boolean] true if encryption is supported
|
496
|
+
def encryption_supported?
|
497
|
+
['0x0300', '0x0302', '0x0311'].include?(@dialect)
|
498
|
+
end
|
499
|
+
|
500
|
+
# Encrypt and send a packet
|
501
|
+
def send_encrypt(packet)
|
502
|
+
begin
|
503
|
+
transform_request = smb3_encrypt(packet.to_binary_s)
|
504
|
+
rescue RubySMB::Error::RubySMBError => e
|
505
|
+
raise RubySMB::Error::EncryptionError, "Error while encrypting #{packet.class.name} packet (SMB #{@dialect}): #{e}"
|
506
|
+
end
|
507
|
+
dispatcher.send_packet(transform_request)
|
508
|
+
end
|
509
|
+
|
510
|
+
# Receives the raw response through the Dispatcher and decrypt the packet.
|
511
|
+
#
|
512
|
+
# @return [String] the raw unencrypted packet
|
513
|
+
def recv_encrypt
|
514
|
+
begin
|
515
|
+
raw_response = dispatcher.recv_packet
|
516
|
+
rescue RubySMB::Error::CommunicationError => e
|
517
|
+
raise RubySMB::Error::EncryptionError, "Communication error with the "\
|
518
|
+
"remote host: #{e.message}. The server supports encryption but was "\
|
519
|
+
"not able to handle the encrypted request."
|
520
|
+
end
|
521
|
+
begin
|
522
|
+
transform_response = RubySMB::SMB2::Packet::TransformHeader.read(raw_response)
|
523
|
+
rescue IOError
|
524
|
+
raise RubySMB::Error::InvalidPacket, 'Not a SMB2 TransformHeader packet'
|
525
|
+
end
|
526
|
+
begin
|
527
|
+
smb3_decrypt(transform_response)
|
528
|
+
rescue RubySMB::Error::RubySMBError => e
|
529
|
+
raise RubySMB::Error::EncryptionError, "Error while decrypting #{transform_response.class.name} packet (SMB #@dialect}): #{e}"
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
340
533
|
# Connects to the supplied share
|
341
534
|
#
|
342
535
|
# @param share [String] the path to the share in `\\server\share_name` format
|
343
536
|
# @return [RubySMB::SMB1::Tree] if talking over SMB1
|
344
537
|
# @return [RubySMB::SMB2::Tree] if talking over SMB2
|
345
538
|
def tree_connect(share)
|
346
|
-
connected_tree = if smb2
|
539
|
+
connected_tree = if smb2 || smb3
|
347
540
|
smb2_tree_connect(share)
|
348
541
|
else
|
349
542
|
smb1_tree_connect(share)
|
@@ -373,6 +566,8 @@ module RubySMB
|
|
373
566
|
self.session_key = ''
|
374
567
|
self.sequence_counter = 0
|
375
568
|
self.smb2_message_id = 0
|
569
|
+
self.client_encryption_key = nil
|
570
|
+
self.server_encryption_key = nil
|
376
571
|
end
|
377
572
|
|
378
573
|
# Requests a NetBIOS Session Service using the provided name.
|
@@ -380,14 +575,19 @@ module RubySMB
|
|
380
575
|
# @param name [String] the NetBIOS name to request
|
381
576
|
# @return [TrueClass] if session request is granted
|
382
577
|
# @raise [RubySMB::Error::NetBiosSessionService] if session request is refused
|
578
|
+
# @raise [RubySMB::Error::InvalidPacket] if the response packet is not a NBSS packet
|
383
579
|
def session_request(name = '*SMBSERVER')
|
384
580
|
session_request = session_request_packet(name)
|
385
581
|
dispatcher.send_packet(session_request, nbss_header: false)
|
386
582
|
raw_response = dispatcher.recv_packet(full_response: true)
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
583
|
+
begin
|
584
|
+
session_header = RubySMB::Nbss::SessionHeader.read(raw_response)
|
585
|
+
if session_header.session_packet_type == RubySMB::Nbss::NEGATIVE_SESSION_RESPONSE
|
586
|
+
negative_session_response = RubySMB::Nbss::NegativeSessionResponse.read(raw_response)
|
587
|
+
raise RubySMB::Error::NetBiosSessionService, "Session Request failed: #{negative_session_response.error_msg}"
|
588
|
+
end
|
589
|
+
rescue IOError
|
590
|
+
raise RubySMB::Error::InvalidPacket, 'Not a NBSS packet'
|
391
591
|
end
|
392
592
|
|
393
593
|
return true
|
@@ -410,5 +610,16 @@ module RubySMB
|
|
410
610
|
session_request
|
411
611
|
end
|
412
612
|
|
613
|
+
def update_preauth_hash(data)
|
614
|
+
unless @preauth_integrity_hash_algorithm
|
615
|
+
raise RubySMB::Error::EncryptionError.new(
|
616
|
+
'Cannot compute the Preauth Integrity Hash value: Preauth Integrity Hash Algorithm is nil'
|
617
|
+
)
|
618
|
+
end
|
619
|
+
@preauth_integrity_hash_value = OpenSSL::Digest.digest(
|
620
|
+
@preauth_integrity_hash_algorithm,
|
621
|
+
@preauth_integrity_hash_value + data.to_binary_s
|
622
|
+
)
|
623
|
+
end
|
413
624
|
end
|
414
625
|
end
|
@@ -54,14 +54,15 @@ module RubySMB
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def smb1_anonymous_auth_response(raw_response)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
57
|
+
packet = RubySMB::SMB1::Packet::SessionSetupLegacyResponse.read(raw_response)
|
58
|
+
|
59
|
+
unless packet.valid?
|
60
|
+
raise RubySMB::Error::InvalidPacket.new(
|
61
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
62
|
+
expected_cmd: RubySMB::SMB1::Packet::SessionSetupLegacyResponse::COMMAND,
|
63
|
+
received_proto: packet.smb_header.protocol,
|
64
|
+
received_cmd: packet.smb_header.command
|
65
|
+
)
|
65
66
|
end
|
66
67
|
packet
|
67
68
|
end
|
@@ -147,14 +148,15 @@ module RubySMB
|
|
147
148
|
|
148
149
|
# Takes the raw binary string and returns a {RubySMB::SMB1::Packet::SessionSetupResponse}
|
149
150
|
def smb1_ntlmssp_final_packet(raw_response)
|
150
|
-
|
151
|
-
packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
|
152
|
-
rescue
|
153
|
-
packet = RubySMB::SMB1::Packet::EmptyPacket.read(raw_response)
|
154
|
-
end
|
151
|
+
packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
|
155
152
|
|
156
|
-
unless packet.
|
157
|
-
raise RubySMB::Error::InvalidPacket
|
153
|
+
unless packet.valid?
|
154
|
+
raise RubySMB::Error::InvalidPacket.new(
|
155
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
156
|
+
expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND,
|
157
|
+
received_proto: packet.smb_header.protocol,
|
158
|
+
received_cmd: packet.smb_header.command
|
159
|
+
)
|
158
160
|
end
|
159
161
|
packet
|
160
162
|
end
|
@@ -162,15 +164,20 @@ module RubySMB
|
|
162
164
|
# Takes the raw binary string and returns a {RubySMB::SMB1::Packet::SessionSetupResponse}
|
163
165
|
def smb1_ntlmssp_challenge_packet(raw_response)
|
164
166
|
packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
|
165
|
-
|
167
|
+
unless packet.valid?
|
168
|
+
raise RubySMB::Error::InvalidPacket.new(
|
169
|
+
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
170
|
+
expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND,
|
171
|
+
received_proto: packet.smb_header.protocol,
|
172
|
+
received_cmd: packet.smb_header.command
|
173
|
+
)
|
174
|
+
end
|
166
175
|
|
176
|
+
status_code = packet.status_code
|
167
177
|
unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED'
|
168
|
-
raise RubySMB::Error::UnexpectedStatusCode, status_code
|
178
|
+
raise RubySMB::Error::UnexpectedStatusCode, status_code
|
169
179
|
end
|
170
180
|
|
171
|
-
unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
|
172
|
-
raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb_header.command} and not #{RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP}"
|
173
|
-
end
|
174
181
|
packet
|
175
182
|
end
|
176
183
|
|
@@ -194,6 +201,9 @@ module RubySMB
|
|
194
201
|
def smb2_authenticate
|
195
202
|
response = smb2_ntlmssp_negotiate
|
196
203
|
challenge_packet = smb2_ntlmssp_challenge_packet(response)
|
204
|
+
if @dialect == '0x0311'
|
205
|
+
update_preauth_hash(challenge_packet)
|
206
|
+
end
|
197
207
|
@session_id = challenge_packet.smb2_header.session_id
|
198
208
|
type2_b64_message = smb2_type2_message(challenge_packet)
|
199
209
|
type3_message = @ntlm_client.init_context(type2_b64_message)
|
@@ -206,28 +216,49 @@ module RubySMB
|
|
206
216
|
raw = smb2_ntlmssp_authenticate(type3_message, @session_id)
|
207
217
|
response = smb2_ntlmssp_final_packet(raw)
|
208
218
|
|
219
|
+
if @smb3 && !@session_encrypt_data && response.session_flags.encrypt_data == 1
|
220
|
+
@session_encrypt_data = true
|
221
|
+
end
|
222
|
+
######
|
223
|
+
# DEBUG
|
224
|
+
#puts "Session ID = #{@session_id.to_binary_s.each_byte.map {|e| '%02x' % e}.join}"
|
225
|
+
#puts "Session key = #{@session_key.each_byte.map {|e| '%02x' % e}.join}"
|
226
|
+
#puts "PreAuthHash = #{@preauth_integrity_hash_value.each_byte.map {|e| '%02x' % e}.join}" if @preauth_integrity_hash_value
|
227
|
+
######
|
228
|
+
|
209
229
|
response.status_code
|
210
230
|
end
|
211
231
|
|
212
232
|
# Takes the raw binary string and returns a {RubySMB::SMB2::Packet::SessionSetupResponse}
|
213
233
|
def smb2_ntlmssp_final_packet(raw_response)
|
214
234
|
packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response)
|
215
|
-
unless packet.
|
216
|
-
raise RubySMB::Error::InvalidPacket
|
235
|
+
unless packet.valid?
|
236
|
+
raise RubySMB::Error::InvalidPacket.new(
|
237
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
238
|
+
expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND,
|
239
|
+
received_proto: packet.smb2_header.protocol,
|
240
|
+
received_cmd: packet.smb2_header.command
|
241
|
+
)
|
217
242
|
end
|
243
|
+
|
218
244
|
packet
|
219
245
|
end
|
220
246
|
|
221
247
|
# Takes the raw binary string and returns a {RubySMB::SMB2::Packet::SessionSetupResponse}
|
222
248
|
def smb2_ntlmssp_challenge_packet(raw_response)
|
223
249
|
packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response)
|
224
|
-
|
225
|
-
|
226
|
-
|
250
|
+
unless packet.valid?
|
251
|
+
raise RubySMB::Error::InvalidPacket.new(
|
252
|
+
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
253
|
+
expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND,
|
254
|
+
received_proto: packet.smb2_header.protocol,
|
255
|
+
received_cmd: packet.smb2_header.command
|
256
|
+
)
|
227
257
|
end
|
228
258
|
|
229
|
-
|
230
|
-
|
259
|
+
status_code = packet.status_code
|
260
|
+
unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED'
|
261
|
+
raise RubySMB::Error::UnexpectedStatusCode, status_code
|
231
262
|
end
|
232
263
|
packet
|
233
264
|
end
|
@@ -238,7 +269,11 @@ module RubySMB
|
|
238
269
|
# @return [String] the binary string response from the server
|
239
270
|
def smb2_ntlmssp_negotiate
|
240
271
|
packet = smb2_ntlmssp_negotiate_packet
|
241
|
-
send_recv(packet)
|
272
|
+
response = send_recv(packet)
|
273
|
+
if @dialect == '0x0311'
|
274
|
+
update_preauth_hash(packet)
|
275
|
+
end
|
276
|
+
response
|
242
277
|
end
|
243
278
|
|
244
279
|
# Creates the {RubySMB::SMB2::Packet::SessionSetupRequest} packet
|
@@ -250,10 +285,7 @@ module RubySMB
|
|
250
285
|
type1_message = ntlm_client.init_context
|
251
286
|
packet = RubySMB::SMB2::Packet::SessionSetupRequest.new
|
252
287
|
packet.set_type1_blob(type1_message.serialize)
|
253
|
-
|
254
|
-
# the Message ID can be out of sync at this point so we re-synch it here.
|
255
|
-
packet.smb2_header.message_id = 1
|
256
|
-
self.smb2_message_id = 2
|
288
|
+
packet.security_mode.signing_enabled = 1
|
257
289
|
packet
|
258
290
|
end
|
259
291
|
|
@@ -276,7 +308,11 @@ module RubySMB
|
|
276
308
|
# @return [String] the raw binary response from the server
|
277
309
|
def smb2_ntlmssp_authenticate(type3_message, user_id)
|
278
310
|
packet = smb2_ntlmssp_auth_packet(type3_message, user_id)
|
279
|
-
send_recv(packet)
|
311
|
+
response = send_recv(packet)
|
312
|
+
if @dialect == '0x0311'
|
313
|
+
update_preauth_hash(packet)
|
314
|
+
end
|
315
|
+
response
|
280
316
|
end
|
281
317
|
|
282
318
|
# Generates the {RubySMB::SMB2::Packet::SessionSetupRequest} packet
|
@@ -289,6 +325,7 @@ module RubySMB
|
|
289
325
|
packet = RubySMB::SMB2::Packet::SessionSetupRequest.new
|
290
326
|
packet.smb2_header.session_id = session_id
|
291
327
|
packet.set_type3_blob(type3_message.serialize)
|
328
|
+
packet.security_mode.signing_enabled = 1
|
292
329
|
packet
|
293
330
|
end
|
294
331
|
|