ruby_smb 1.1.0 → 2.0.4
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 -5
- data/Gemfile +6 -2
- data/examples/anonymous_auth.rb +3 -3
- data/examples/append_file.rb +10 -8
- data/examples/authenticate.rb +9 -5
- data/examples/delete_file.rb +8 -6
- data/examples/enum_registry_key.rb +5 -4
- data/examples/enum_registry_values.rb +5 -4
- data/examples/list_directory.rb +8 -6
- data/examples/negotiate.rb +51 -8
- data/examples/negotiate_with_netbios_service.rb +9 -5
- data/examples/net_share_enum_all.rb +6 -4
- data/examples/pipes.rb +11 -12
- data/examples/query_service_status.rb +64 -0
- data/examples/read_file.rb +8 -6
- data/examples/read_file_encryption.rb +56 -0
- data/examples/read_registry_key_value.rb +6 -5
- data/examples/rename_file.rb +9 -7
- data/examples/tree_connect.rb +7 -5
- data/examples/write_file.rb +9 -7
- data/lib/ruby_smb.rb +4 -0
- data/lib/ruby_smb/client.rb +246 -26
- data/lib/ruby_smb/client/authentication.rb +32 -18
- data/lib/ruby_smb/client/echo.rb +2 -4
- data/lib/ruby_smb/client/encryption.rb +62 -0
- data/lib/ruby_smb/client/negotiation.rb +156 -16
- data/lib/ruby_smb/client/signing.rb +19 -0
- data/lib/ruby_smb/client/tree_connect.rb +6 -8
- data/lib/ruby_smb/client/utils.rb +24 -17
- data/lib/ruby_smb/client/winreg.rb +1 -1
- data/lib/ruby_smb/crypto.rb +30 -0
- data/lib/ruby_smb/dcerpc.rb +2 -0
- data/lib/ruby_smb/dcerpc/error.rb +3 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +209 -44
- data/lib/ruby_smb/dcerpc/request.rb +13 -0
- data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
- data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +9 -6
- data/lib/ruby_smb/dcerpc/svcctl.rb +479 -0
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +48 -0
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +35 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +31 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +44 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
- data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/winreg.rb +98 -17
- data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +73 -0
- data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +4 -4
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +7 -6
- data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +10 -10
- data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +37 -0
- data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
- data/lib/ruby_smb/dispatcher/base.rb +1 -1
- data/lib/ruby_smb/dispatcher/socket.rb +5 -4
- data/lib/ruby_smb/error.rb +49 -6
- data/lib/ruby_smb/field/stringz16.rb +17 -1
- data/lib/ruby_smb/generic_packet.rb +11 -1
- data/lib/ruby_smb/nbss/session_header.rb +4 -4
- data/lib/ruby_smb/smb1/commands.rb +1 -1
- data/lib/ruby_smb/smb1/file.rb +13 -28
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +1 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +2 -2
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -2
- data/lib/ruby_smb/smb1/packet/write_andx_request.rb +1 -1
- data/lib/ruby_smb/smb1/pipe.rb +8 -8
- data/lib/ruby_smb/smb1/tree.rb +25 -12
- 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 +59 -77
- 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/compression_transform_header.rb +41 -0
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -14
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +50 -4
- data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +92 -6
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +8 -26
- data/lib/ruby_smb/smb2/pipe.rb +8 -20
- data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
- data/lib/ruby_smb/smb2/tree.rb +44 -28
- data/lib/ruby_smb/version.rb +1 -1
- data/ruby_smb.gemspec +3 -1
- data/spec/lib/ruby_smb/client_spec.rb +1408 -70
- data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
- data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +1396 -77
- data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +161 -0
- data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +49 -12
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +191 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +78 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +59 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +72 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +46 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +512 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +110 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +0 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +9 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +17 -17
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +11 -23
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +57 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +227 -41
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +12 -12
- data/spec/lib/ruby_smb/error_spec.rb +88 -0
- data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
- data/spec/lib/ruby_smb/generic_packet_spec.rb +7 -0
- data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
- data/spec/lib/ruby_smb/smb1/file_spec.rb +1 -3
- 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/pipe_spec.rb +30 -5
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +22 -0
- 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 +147 -71
- 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/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/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 -30
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +9 -45
- data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +111 -9
- metadata +194 -75
- metadata.gz.sig +2 -1
@@ -4,7 +4,7 @@ module RubySMB
|
|
4
4
|
# A SMB1 SMB_COM_SESSION_SETUP_ANDX Request Packet, without NTLMSSP as defined in
|
5
5
|
# [2.2.4.53.1 Request](https://msdn.microsoft.com/en-us/library/ee441849.aspx)
|
6
6
|
class SessionSetupLegacyRequest < RubySMB::GenericPacket
|
7
|
-
COMMAND = RubySMB::SMB1::Commands::
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP_ANDX
|
8
8
|
|
9
9
|
# A SMB1 Parameter Block as defined by the {SessionSetupRequest}
|
10
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module RubySMB
|
2
2
|
module SMB1
|
3
3
|
module Packet
|
4
|
-
# A SMB1
|
4
|
+
# A SMB1 SMB_COM_SESSION_SETUP_ANDX Legacy Response Packet as defined in
|
5
5
|
# [2.2.4.53.2 Response](https://msdn.microsoft.com/en-us/library/ee442143.aspx)
|
6
6
|
class SessionSetupLegacyResponse < RubySMB::GenericPacket
|
7
|
-
COMMAND = RubySMB::SMB1::Commands::
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP_ANDX
|
8
8
|
|
9
9
|
# A SMB1 Parameter Block as defined by the {SessionSetupResponse}
|
10
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
@@ -4,7 +4,7 @@ module RubySMB
|
|
4
4
|
# A SMB1 SMB_COM_SESSION_SETUP_ANDX Request Packet as defined in
|
5
5
|
# [2.2.4.6.1](https://msdn.microsoft.com/en-us/library/cc246328.aspx)
|
6
6
|
class SessionSetupRequest < RubySMB::GenericPacket
|
7
|
-
COMMAND = RubySMB::SMB1::Commands::
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP_ANDX
|
8
8
|
|
9
9
|
# A SMB1 Parameter Block as defined by the {SessionSetupRequest}
|
10
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module RubySMB
|
2
2
|
module SMB1
|
3
3
|
module Packet
|
4
|
-
# A SMB1
|
4
|
+
# A SMB1 SMB_COM_SESSION_SETUP_ANDX Response Packet as defined in
|
5
5
|
# [2.2.4.6.2](https://msdn.microsoft.com/en-us/library/cc246329.aspx)
|
6
6
|
class SessionSetupResponse < RubySMB::GenericPacket
|
7
|
-
COMMAND = RubySMB::SMB1::Commands::
|
7
|
+
COMMAND = RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP_ANDX
|
8
8
|
|
9
9
|
# A SMB1 Parameter Block as defined by the {SessionSetupResponse}
|
10
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
data/lib/ruby_smb/smb1/pipe.rb
CHANGED
@@ -16,10 +16,12 @@ module RubySMB
|
|
16
16
|
def initialize(tree:, response:, name:)
|
17
17
|
raise ArgumentError, 'No Name Provided' if name.nil?
|
18
18
|
case name
|
19
|
-
when 'srvsvc'
|
19
|
+
when 'srvsvc', '\\srvsvc'
|
20
20
|
extend RubySMB::Dcerpc::Srvsvc
|
21
|
-
when 'winreg'
|
21
|
+
when 'winreg', '\\winreg'
|
22
22
|
extend RubySMB::Dcerpc::Winreg
|
23
|
+
when 'svcctl', '\\svcctl'
|
24
|
+
extend RubySMB::Dcerpc::Svcctl
|
23
25
|
end
|
24
26
|
super(tree: tree, response: response, name: name)
|
25
27
|
end
|
@@ -41,13 +43,12 @@ module RubySMB
|
|
41
43
|
raise RubySMB::Error::InvalidPacket.new(
|
42
44
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
43
45
|
expected_cmd: RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest::COMMAND,
|
44
|
-
|
45
|
-
received_cmd: response.smb_header.command
|
46
|
+
packet: response
|
46
47
|
)
|
47
48
|
end
|
48
49
|
|
49
50
|
unless response.status_code == WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW or response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
50
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
51
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
51
52
|
end
|
52
53
|
|
53
54
|
response
|
@@ -100,13 +101,12 @@ module RubySMB
|
|
100
101
|
raise RubySMB::Error::InvalidPacket.new(
|
101
102
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
102
103
|
expected_cmd: RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse::COMMAND,
|
103
|
-
|
104
|
-
received_cmd: trans_nmpipe_response.smb_header.command
|
104
|
+
packet: trans_nmpipe_response
|
105
105
|
)
|
106
106
|
end
|
107
107
|
unless [WindowsError::NTStatus::STATUS_SUCCESS,
|
108
108
|
WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW].include?(trans_nmpipe_response.status_code)
|
109
|
-
raise RubySMB::Error::UnexpectedStatusCode, trans_nmpipe_response.status_code
|
109
|
+
raise RubySMB::Error::UnexpectedStatusCode, trans_nmpipe_response.status_code
|
110
110
|
end
|
111
111
|
|
112
112
|
raw_data = trans_nmpipe_response.data_block.trans_data.read_data.to_binary_s
|
data/lib/ruby_smb/smb1/tree.rb
CHANGED
@@ -49,13 +49,20 @@ module RubySMB
|
|
49
49
|
raise RubySMB::Error::InvalidPacket.new(
|
50
50
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
51
51
|
expected_cmd: RubySMB::SMB1::Packet::TreeDisconnectResponse::COMMAND,
|
52
|
-
|
53
|
-
received_cmd: response.smb_header.command
|
52
|
+
packet: response
|
54
53
|
)
|
55
54
|
end
|
56
55
|
response.status_code
|
57
56
|
end
|
58
57
|
|
58
|
+
def open_pipe(opts)
|
59
|
+
# Make sure we don't modify the caller's hash options
|
60
|
+
opts = opts.dup
|
61
|
+
opts[:filename] = opts[:filename].dup
|
62
|
+
opts[:filename].prepend('\\') unless opts[:filename].start_with?('\\')
|
63
|
+
open_file(opts)
|
64
|
+
end
|
65
|
+
|
59
66
|
# Open a file on the remote share.
|
60
67
|
#
|
61
68
|
# @example
|
@@ -123,18 +130,26 @@ module RubySMB
|
|
123
130
|
raw_response = @client.send_recv(nt_create_andx_request)
|
124
131
|
response = RubySMB::SMB1::Packet::NtCreateAndxResponse.read(raw_response)
|
125
132
|
unless response.valid?
|
133
|
+
if response.is_a?(RubySMB::SMB1::Packet::EmptyPacket) &&
|
134
|
+
response.smb_header.protocol == RubySMB::SMB1::SMB_PROTOCOL_ID &&
|
135
|
+
response.smb_header.command == response.original_command
|
136
|
+
raise RubySMB::Error::InvalidPacket.new(
|
137
|
+
'The response seems to be an SMB1 NtCreateAndxResponse but an '\
|
138
|
+
'error occurs while parsing it. It is probably missing the '\
|
139
|
+
'required extended information.'
|
140
|
+
)
|
141
|
+
end
|
126
142
|
raise RubySMB::Error::InvalidPacket.new(
|
127
143
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
128
144
|
expected_cmd: RubySMB::SMB1::Packet::NtCreateAndxResponse::COMMAND,
|
129
|
-
|
130
|
-
received_cmd: response.smb_header.command
|
145
|
+
packet: response
|
131
146
|
)
|
132
147
|
end
|
133
148
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
134
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
149
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
135
150
|
end
|
136
151
|
|
137
|
-
case response.parameter_block.resource_type
|
152
|
+
case response.parameter_block.resource_type
|
138
153
|
when RubySMB::SMB1::ResourceType::BYTE_MODE_PIPE, RubySMB::SMB1::ResourceType::MESSAGE_MODE_PIPE
|
139
154
|
RubySMB::SMB1::Pipe.new(name: filename, tree: self, response: response)
|
140
155
|
when RubySMB::SMB1::ResourceType::DISK
|
@@ -186,12 +201,11 @@ module RubySMB
|
|
186
201
|
raise RubySMB::Error::InvalidPacket.new(
|
187
202
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
188
203
|
expected_cmd: RubySMB::SMB1::Packet::Trans2::FindFirst2Response::COMMAND,
|
189
|
-
|
190
|
-
received_cmd: response.smb_header.command
|
204
|
+
packet: response
|
191
205
|
)
|
192
206
|
end
|
193
207
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
194
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
208
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
195
209
|
end
|
196
210
|
|
197
211
|
results = response.results(type, unicode: unicode)
|
@@ -221,12 +235,11 @@ module RubySMB
|
|
221
235
|
raise RubySMB::Error::InvalidPacket.new(
|
222
236
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
223
237
|
expected_cmd: RubySMB::SMB1::Packet::Trans2::FindNext2Response::COMMAND,
|
224
|
-
|
225
|
-
received_cmd: response.smb_header.command
|
238
|
+
packet: response
|
226
239
|
)
|
227
240
|
end
|
228
241
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
229
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
242
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
230
243
|
end
|
231
244
|
|
232
245
|
results += response.results(type, unicode: unicode)
|
@@ -4,7 +4,8 @@ module RubySMB
|
|
4
4
|
# The SessionsFlags bit-field for a {RubySMB::SMB2::Packet::SessionSetupResponse}
|
5
5
|
class SessionFlags < BinData::Record
|
6
6
|
endian :little
|
7
|
-
|
7
|
+
bit5 :reserved3, label: 'Reserved', initial_value: 0
|
8
|
+
bit1 :encrypt_data, label: 'Encrypt Data', initial_value: 0
|
8
9
|
bit1 :null, label: 'ASYNC Command', initial_value: 0
|
9
10
|
bit1 :guest, label: 'Is Guest?', initial_value: 0
|
10
11
|
resume_byte_alignment
|
@@ -8,7 +8,7 @@ module RubySMB
|
|
8
8
|
bit2 :reserved1, label: 'Reserved Space'
|
9
9
|
bit1 :vdo_caching, label: 'VDO Caching'
|
10
10
|
bit1 :auto_caching, label: 'Auto Caching'
|
11
|
-
bit2 :reserved2
|
11
|
+
bit2 :reserved2, label: 'Reserved Space'
|
12
12
|
bit1 :dfs_root, label: 'DFS Root'
|
13
13
|
bit1 :dfs, label: 'DFS'
|
14
14
|
# byte boundary
|
@@ -20,9 +20,11 @@ module RubySMB
|
|
20
20
|
bit1 :namespace_caching, label: 'Namespace Caching'
|
21
21
|
bit1 :shared_delete, label: 'Force Shared Delete'
|
22
22
|
bit1 :restrict_exclusive_opens, label: 'Restrict Exclusive Opens'
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
# byte boundary
|
24
|
+
bit5 :reserved3, label: 'Reserved Space'
|
25
|
+
bit1 :identity_remoting, label: 'Identity Remoting'
|
26
|
+
bit2 :reserved4, label: 'Reserved Space'
|
27
|
+
bit8 :reserved5, label: 'Reserved Space'
|
26
28
|
|
27
29
|
def caching_type
|
28
30
|
if vdo_caching == 1 && auto_caching.zero?
|
data/lib/ruby_smb/smb2/file.rb
CHANGED
@@ -52,7 +52,12 @@ module RubySMB
|
|
52
52
|
# @return [RubySMB::SMB2::Tree]
|
53
53
|
attr_accessor :tree
|
54
54
|
|
55
|
-
|
55
|
+
# Whether or not the share associated with this tree connect needs to be encrypted (SMB 3.x)
|
56
|
+
# @!attribute [rw] tree_connect_encrypt_data
|
57
|
+
# @return [Boolean]
|
58
|
+
attr_accessor :tree_connect_encrypt_data
|
59
|
+
|
60
|
+
def initialize(tree:, response:, name:, encrypt: false)
|
56
61
|
raise ArgumentError, 'No Tree Provided' if tree.nil?
|
57
62
|
raise ArgumentError, 'No Response Provided' if response.nil?
|
58
63
|
|
@@ -66,6 +71,7 @@ module RubySMB
|
|
66
71
|
@last_write = response.last_write.to_datetime
|
67
72
|
@size = response.end_of_file
|
68
73
|
@size_on_disk = response.allocation_size
|
74
|
+
@tree_connect_encrypt_data = encrypt
|
69
75
|
end
|
70
76
|
|
71
77
|
# Appends the supplied data to the end of the file.
|
@@ -83,18 +89,17 @@ module RubySMB
|
|
83
89
|
# @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
|
84
90
|
def close
|
85
91
|
close_request = set_header_fields(RubySMB::SMB2::Packet::CloseRequest.new)
|
86
|
-
raw_response = tree.client.send_recv(close_request)
|
92
|
+
raw_response = tree.client.send_recv(close_request, encrypt: @tree_connect_encrypt_data)
|
87
93
|
response = RubySMB::SMB2::Packet::CloseResponse.read(raw_response)
|
88
94
|
unless response.valid?
|
89
95
|
raise RubySMB::Error::InvalidPacket.new(
|
90
96
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
91
97
|
expected_cmd: RubySMB::SMB2::Packet::CloseResponse::COMMAND,
|
92
|
-
|
93
|
-
received_cmd: response.smb2_header.command
|
98
|
+
packet: response
|
94
99
|
)
|
95
100
|
end
|
96
101
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
97
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
102
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
98
103
|
end
|
99
104
|
response.status_code
|
100
105
|
end
|
@@ -109,25 +114,26 @@ module RubySMB
|
|
109
114
|
# @raise [RubySMB::Error::InvalidPacket] if the response is not a ReadResponse packet
|
110
115
|
# @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
|
111
116
|
def read(bytes: size, offset: 0)
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
117
|
+
max_read = tree.client.server_max_read_size
|
118
|
+
max_read = 65536 unless tree.client.server_supports_multi_credit
|
119
|
+
atomic_read_size = [bytes, max_read].min
|
120
|
+
credit_charge = 0
|
121
|
+
if tree.client.server_supports_multi_credit
|
122
|
+
credit_charge = (atomic_read_size - 1) / 65536 + 1
|
123
|
+
end
|
124
|
+
|
125
|
+
read_request = read_packet(read_length: atomic_read_size, offset: offset, credit_charge: credit_charge)
|
126
|
+
raw_response = tree.client.send_recv(read_request, encrypt: @tree_connect_encrypt_data)
|
120
127
|
response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
|
121
128
|
unless response.valid?
|
122
129
|
raise RubySMB::Error::InvalidPacket.new(
|
123
130
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
124
131
|
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
125
|
-
|
126
|
-
received_cmd: response.smb2_header.command
|
132
|
+
packet: response
|
127
133
|
)
|
128
134
|
end
|
129
135
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
130
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
136
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
131
137
|
end
|
132
138
|
|
133
139
|
data = response.buffer.to_binary_s
|
@@ -136,21 +142,20 @@ module RubySMB
|
|
136
142
|
|
137
143
|
while remaining_bytes > 0
|
138
144
|
offset += atomic_read_size
|
139
|
-
atomic_read_size = remaining_bytes if remaining_bytes <
|
145
|
+
atomic_read_size = remaining_bytes if remaining_bytes < max_read
|
140
146
|
|
141
|
-
read_request = read_packet(read_length: atomic_read_size, offset: offset)
|
142
|
-
raw_response = tree.client.send_recv(read_request)
|
147
|
+
read_request = read_packet(read_length: atomic_read_size, offset: offset, credit_charge: credit_charge)
|
148
|
+
raw_response = tree.client.send_recv(read_request, encrypt: @tree_connect_encrypt_data)
|
143
149
|
response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
|
144
150
|
unless response.valid?
|
145
151
|
raise RubySMB::Error::InvalidPacket.new(
|
146
152
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
147
153
|
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
148
|
-
|
149
|
-
received_cmd: response.smb2_header.command
|
154
|
+
packet: response
|
150
155
|
)
|
151
156
|
end
|
152
157
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
153
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
158
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
154
159
|
end
|
155
160
|
|
156
161
|
data << response.buffer.to_binary_s
|
@@ -163,40 +168,29 @@ module RubySMB
|
|
163
168
|
#
|
164
169
|
# @param bytes [Integer] the number of bytes to read
|
165
170
|
# @param offset [Integer] the byte offset in the file to start reading from
|
171
|
+
# @param credit_charge [Integer] the number of credits that this request consumes
|
166
172
|
# @return [RubySMB::SMB2::Packet::ReadRequest] the data read from the file
|
167
|
-
def read_packet(read_length: 0, offset: 0)
|
173
|
+
def read_packet(read_length: 0, offset: 0, credit_charge: 1)
|
168
174
|
read_request = set_header_fields(RubySMB::SMB2::Packet::ReadRequest.new)
|
169
175
|
read_request.read_length = read_length
|
170
176
|
read_request.offset = offset
|
177
|
+
read_request.smb2_header.credit_charge = credit_charge
|
171
178
|
read_request
|
172
179
|
end
|
173
|
-
|
180
|
+
|
174
181
|
def send_recv_read(read_length: 0, offset: 0)
|
175
182
|
read_request = read_packet(read_length: read_length, offset: offset)
|
176
|
-
raw_response = tree.client.send_recv(read_request)
|
183
|
+
raw_response = tree.client.send_recv(read_request, encrypt: @tree_connect_encrypt_data)
|
177
184
|
response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
|
178
185
|
unless response.valid?
|
179
186
|
raise RubySMB::Error::InvalidPacket.new(
|
180
187
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
181
188
|
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
182
|
-
|
183
|
-
received_cmd: response.smb2_header.command
|
189
|
+
packet: response
|
184
190
|
)
|
185
191
|
end
|
186
|
-
|
187
|
-
|
188
|
-
raw_response = tree.client.dispatcher.recv_packet
|
189
|
-
response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
|
190
|
-
unless response.valid?
|
191
|
-
raise RubySMB::Error::InvalidPacket.new(
|
192
|
-
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
193
|
-
expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
|
194
|
-
received_proto: response.smb2_header.protocol,
|
195
|
-
received_cmd: response.smb2_header.command
|
196
|
-
)
|
197
|
-
end
|
198
|
-
elsif response.status_code != WindowsError::NTStatus::STATUS_SUCCESS
|
199
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
192
|
+
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
193
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
200
194
|
end
|
201
195
|
response.buffer.to_binary_s
|
202
196
|
end
|
@@ -206,14 +200,13 @@ module RubySMB
|
|
206
200
|
# @return [WindowsError::ErrorCode] the NTStatus Response code
|
207
201
|
# @raise [RubySMB::Error::InvalidPacket] if the response is not a SetInfoResponse packet
|
208
202
|
def delete
|
209
|
-
raw_response = tree.client.send_recv(delete_packet)
|
203
|
+
raw_response = tree.client.send_recv(delete_packet, encrypt: @tree_connect_encrypt_data)
|
210
204
|
response = RubySMB::SMB2::Packet::SetInfoResponse.read(raw_response)
|
211
205
|
unless response.valid?
|
212
206
|
raise RubySMB::Error::InvalidPacket.new(
|
213
207
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
214
208
|
expected_cmd: RubySMB::SMB2::Packet::SetInfoResponse::COMMAND,
|
215
|
-
|
216
|
-
received_cmd: response.smb2_header.command
|
209
|
+
packet: response
|
217
210
|
)
|
218
211
|
end
|
219
212
|
response.smb2_header.nt_status.to_nt_status
|
@@ -246,29 +239,30 @@ module RubySMB
|
|
246
239
|
# @return [WindowsError::ErrorCode] the NTStatus code returned from the operation
|
247
240
|
# @raise [RubySMB::Error::InvalidPacket] if the response is not a WriteResponse packet
|
248
241
|
def write(data:'', offset: 0)
|
242
|
+
max_write = tree.client.server_max_write_size
|
243
|
+
max_write = 65536 unless tree.client.server_supports_multi_credit
|
249
244
|
buffer = data.dup
|
250
245
|
bytes = data.length
|
251
|
-
atomic_write_size =
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
246
|
+
atomic_write_size = [bytes, max_write].min
|
247
|
+
credit_charge = 0
|
248
|
+
if tree.client.server_supports_multi_credit
|
249
|
+
credit_charge = (atomic_write_size - 1) / 65536 + 1
|
250
|
+
end
|
256
251
|
|
257
252
|
while buffer.length > 0 do
|
258
|
-
write_request = write_packet(data: buffer.slice!(0,atomic_write_size), offset: offset)
|
259
|
-
raw_response = tree.client.send_recv(write_request)
|
253
|
+
write_request = write_packet(data: buffer.slice!(0, atomic_write_size), offset: offset, credit_charge: credit_charge)
|
254
|
+
raw_response = tree.client.send_recv(write_request, encrypt: @tree_connect_encrypt_data)
|
260
255
|
response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
|
261
256
|
unless response.valid?
|
262
257
|
raise RubySMB::Error::InvalidPacket.new(
|
263
258
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
264
259
|
expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
|
265
|
-
|
266
|
-
received_cmd: response.smb2_header.command
|
260
|
+
packet: response
|
267
261
|
)
|
268
262
|
end
|
269
263
|
status = response.smb2_header.nt_status.to_nt_status
|
270
264
|
|
271
|
-
offset+= atomic_write_size
|
265
|
+
offset += atomic_write_size
|
272
266
|
return status unless status == WindowsError::NTStatus::STATUS_SUCCESS
|
273
267
|
end
|
274
268
|
|
@@ -279,58 +273,46 @@ module RubySMB
|
|
279
273
|
#
|
280
274
|
# @param data [String] the data to write to the file
|
281
275
|
# @param offset [Integer] the offset in the file to start writing from
|
276
|
+
# @param credit_charge [Integer] the number of credits that this request consumes
|
282
277
|
# @return []RubySMB::SMB2::Packet::WriteRequest] the request packet
|
283
|
-
def write_packet(data:'', offset: 0)
|
278
|
+
def write_packet(data:'', offset: 0, credit_charge: 1)
|
284
279
|
write_request = set_header_fields(RubySMB::SMB2::Packet::WriteRequest.new)
|
285
280
|
write_request.write_offset = offset
|
286
281
|
write_request.buffer = data
|
282
|
+
write_request.smb2_header.credit_charge = credit_charge
|
287
283
|
write_request
|
288
284
|
end
|
289
|
-
|
285
|
+
|
290
286
|
def send_recv_write(data:'', offset: 0)
|
291
287
|
pkt = write_packet(data: data, offset: offset)
|
292
|
-
raw_response = tree.client.send_recv(pkt)
|
288
|
+
raw_response = tree.client.send_recv(pkt, encrypt: @tree_connect_encrypt_data)
|
293
289
|
response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
|
294
290
|
unless response.valid?
|
295
291
|
raise RubySMB::Error::InvalidPacket.new(
|
296
292
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
297
293
|
expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
|
298
|
-
|
299
|
-
received_cmd: response.smb2_header.command
|
294
|
+
packet: response
|
300
295
|
)
|
301
296
|
end
|
302
|
-
|
303
|
-
|
304
|
-
raw_response = tree.client.dispatcher.recv_packet
|
305
|
-
response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
|
306
|
-
unless response.valid?
|
307
|
-
raise RubySMB::Error::InvalidPacket.new(
|
308
|
-
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
309
|
-
expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
|
310
|
-
received_proto: response.smb2_header.protocol,
|
311
|
-
received_cmd: response.smb2_header.command
|
312
|
-
)
|
313
|
-
end
|
314
|
-
elsif response.status_code != WindowsError::NTStatus::STATUS_SUCCESS
|
315
|
-
raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
|
297
|
+
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
298
|
+
raise RubySMB::Error::UnexpectedStatusCode, response.status_code
|
316
299
|
end
|
317
300
|
response.write_count
|
318
301
|
end
|
319
|
-
|
302
|
+
|
320
303
|
# Rename a file
|
321
304
|
#
|
322
305
|
# @param new_file_name [String] the new name
|
323
306
|
# @return [WindowsError::ErrorCode] the NTStatus Response code
|
324
307
|
# @raise [RubySMB::Error::InvalidPacket] if the response is not a SetInfoResponse packet
|
325
308
|
def rename(new_file_name)
|
326
|
-
raw_response = tree.client.send_recv(rename_packet(new_file_name))
|
309
|
+
raw_response = tree.client.send_recv(rename_packet(new_file_name), encrypt: @tree_connect_encrypt_data)
|
327
310
|
response = RubySMB::SMB2::Packet::SetInfoResponse.read(raw_response)
|
328
311
|
unless response.valid?
|
329
312
|
raise RubySMB::Error::InvalidPacket.new(
|
330
313
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
331
314
|
expected_cmd: RubySMB::SMB2::Packet::SetInfoResponse::COMMAND,
|
332
|
-
|
333
|
-
received_cmd: response.smb2_header.command
|
315
|
+
packet: response
|
334
316
|
)
|
335
317
|
end
|
336
318
|
response.smb2_header.nt_status.to_nt_status
|