ruby_smb 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/ruby_smb/client.rb +26 -4
  5. data/lib/ruby_smb/client/authentication.rb +43 -25
  6. data/lib/ruby_smb/client/echo.rb +20 -2
  7. data/lib/ruby_smb/client/negotiation.rb +27 -12
  8. data/lib/ruby_smb/client/tree_connect.rb +20 -14
  9. data/lib/ruby_smb/error.rb +40 -1
  10. data/lib/ruby_smb/generic_packet.rb +33 -4
  11. data/lib/ruby_smb/smb1/dcerpc.rb +7 -2
  12. data/lib/ruby_smb/smb1/file.rb +60 -11
  13. data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
  14. data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
  15. data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
  16. data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
  17. data/lib/ruby_smb/smb1/packet/empty_packet.rb +7 -0
  18. data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
  19. data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
  20. data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
  21. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
  22. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
  23. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
  24. data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
  25. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
  26. data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
  27. data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
  28. data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
  29. data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
  30. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
  31. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
  32. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +2 -1
  33. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
  34. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -1
  35. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
  36. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
  37. data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
  38. data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
  39. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
  40. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
  41. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
  42. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
  43. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
  44. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
  45. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
  46. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
  47. data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
  48. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
  49. data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
  50. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
  51. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
  52. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
  53. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
  54. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
  55. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
  56. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +2 -5
  57. data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
  58. data/lib/ruby_smb/smb1/pipe.rb +8 -3
  59. data/lib/ruby_smb/smb1/tree.rb +40 -2
  60. data/lib/ruby_smb/smb2/dcerpc.rb +7 -2
  61. data/lib/ruby_smb/smb2/file.rb +97 -1
  62. data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
  63. data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
  64. data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
  65. data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
  66. data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
  67. data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
  68. data/lib/ruby_smb/smb2/packet/error_packet.rb +7 -0
  69. data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
  70. data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
  71. data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
  72. data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
  73. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +2 -5
  74. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +2 -1
  75. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
  76. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
  77. data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
  78. data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
  79. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
  80. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
  81. data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
  82. data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
  83. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +2 -5
  84. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +8 -2
  85. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
  86. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
  87. data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
  88. data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
  89. data/lib/ruby_smb/smb2/pipe.rb +9 -9
  90. data/lib/ruby_smb/smb2/tree.rb +44 -6
  91. data/lib/ruby_smb/version.rb +1 -1
  92. data/spec/lib/ruby_smb/client_spec.rb +123 -11
  93. data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
  94. data/spec/lib/ruby_smb/smb1/file_spec.rb +182 -1
  95. data/spec/lib/ruby_smb/smb1/packet/{error_packet_spec.rb → empty_packet_spec.rb} +21 -0
  96. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
  97. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
  98. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
  99. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +63 -2
  100. data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
  101. data/spec/lib/ruby_smb/smb2/file_spec.rb +295 -2
  102. data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +51 -0
  103. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
  104. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +8 -0
  105. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +69 -3
  106. data/spec/lib/ruby_smb/smb2/tree_spec.rb +214 -0
  107. metadata +6 -4
  108. metadata.gz.sig +0 -0
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # This class represents an SMB1 TreeConnect Request Packet as defined in
5
5
  # [2.2.4.7.1 Client Request Extensions](https://msdn.microsoft.com/en-us/library/cc246330.aspx)
6
6
  class TreeConnectRequest < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
8
+
7
9
  # A SMB1 Parameter Block as defined by the {TreeConnectRequest}
8
10
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
9
11
  and_x_block :andx_block
@@ -22,10 +24,6 @@ module RubySMB
22
24
  parameter_block :parameter_block
23
25
  data_block :data_block
24
26
 
25
- def initialize_instance
26
- super
27
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
28
- end
29
27
  end
30
28
  end
31
29
  end
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # A SMB1 TreeConnect Response Packet as defined in
5
5
  # [2.2.4.7.2 Server Response Extensions](https://msdn.microsoft.com/en-us/library/cc246331.aspx)
6
6
  class TreeConnectResponse < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
8
+
7
9
  # A SMB1 Parameter Block as defined by the {SessionSetupResponse}
8
10
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
9
11
  and_x_block :andx_block
@@ -24,7 +26,6 @@ module RubySMB
24
26
 
25
27
  def initialize_instance
26
28
  super
27
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
28
29
  smb_header.flags.reply = 1
29
30
  end
30
31
 
@@ -34,12 +35,17 @@ module RubySMB
34
35
  #
35
36
  # @return [RubySMB::SMB1::BitField::DirectoryAccessMask] if a directory was connected to
36
37
  # @return [RubySMB::SMB1::BitField::FileAccessMask] if anything else was connected to
38
+ # @raise [RubySMB::Error::InvalidBitField] if ACCESS_MASK bit field is not valid
37
39
  def access_rights
38
40
  if is_directory?
39
41
  parameter_block.access_rights
40
42
  else
41
43
  mask = parameter_block.access_rights.to_binary_s
42
- RubySMB::SMB1::BitField::FileAccessMask.read(mask)
44
+ begin
45
+ RubySMB::SMB1::BitField::FileAccessMask.read(mask)
46
+ rescue IOError
47
+ raise RubySMB::Error::InvalidBitField, 'Invalid ACCESS_MASK for the Maximal Share Access Rights'
48
+ end
43
49
  end
44
50
  end
45
51
 
@@ -54,7 +60,11 @@ module RubySMB
54
60
  parameter_block.guest_access_rights
55
61
  else
56
62
  mask = parameter_block.guest_access_rights.to_binary_s
57
- RubySMB::SMB1::BitField::FileAccessMask.read(mask)
63
+ begin
64
+ RubySMB::SMB1::BitField::FileAccessMask.read(mask)
65
+ rescue IOError
66
+ raise RubySMB::Error::InvalidBitField, 'Invalid ACCESS_MASK for the Guest Share Access Rights'
67
+ end
58
68
  end
59
69
  end
60
70
 
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # This class represents an SMB1 TreeDisonnect Request Packet as defined in
5
5
  # [2.2.4.51.1 Request](https://msdn.microsoft.com/en-us/library/ee441622.aspx)
6
6
  class TreeDisconnectRequest < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
8
+
7
9
  # The Parameter Block for this packet is empty save the Word Count
8
10
  # The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
@@ -17,10 +19,6 @@ module RubySMB
17
19
  parameter_block :parameter_block
18
20
  data_block :data_block
19
21
 
20
- def initialize_instance
21
- super
22
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
23
- end
24
22
  end
25
23
  end
26
24
  end
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # This class represents an SMB1 TreeDisonnect Response Packet as defined in
5
5
  # [2.2.4.51.2 Response](https://msdn.microsoft.com/en-us/library/ee441823.aspx)
6
6
  class TreeDisconnectResponse < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
8
+
7
9
  # The Parameter Block for this packet is empty save the Word Count
8
10
  # The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
@@ -19,7 +21,6 @@ module RubySMB
19
21
 
20
22
  def initialize_instance
21
23
  super
22
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
23
24
  smb_header.flags.reply = 1
24
25
  end
25
26
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # [2.2.4.43.1 Request](https://msdn.microsoft.com/en-us/library/ee441954.aspx)
6
6
  # [2.2.4.3.1 Client Request Extensions](https://msdn.microsoft.com/en-us/library/ff469893.aspx)
7
7
  class WriteAndxRequest < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
9
+
8
10
  # A SMB1 Parameter Block as defined by the {WriteAndxRequest}
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
10
12
  endian :little
@@ -49,11 +51,6 @@ module RubySMB
49
51
  parameter_block :parameter_block
50
52
  data_block :data_block
51
53
 
52
- def initialize_instance
53
- super
54
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
55
- end
56
-
57
54
  # Specifies whether the offset is a 32-bit (default) or 64-bit value. When `is_64_bit`
58
55
  # is true, a 64-bit offset will be used and the OffsetHigh field will be added to the structure.
59
56
  #
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # [2.2.4.43.2 Response](https://msdn.microsoft.com/en-us/library/ee441673.aspx)
6
6
  # [2.2.4.3.2 Server Response Extensions](https://msdn.microsoft.com/en-us/library/ff469858.aspx)
7
7
  class WriteAndxResponse < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
9
+
8
10
  # A SMB1 Parameter Block as defined by the {WriteAndxResponse}
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
10
12
  endian :little
@@ -26,7 +28,6 @@ module RubySMB
26
28
 
27
29
  def initialize_instance
28
30
  super
29
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
30
31
  smb_header.flags.reply = 1
31
32
  end
32
33
  end
@@ -26,14 +26,19 @@ module RubySMB
26
26
  packet = @tree.set_header_fields(packet)
27
27
  raw_response = @tree.client.send_recv(packet)
28
28
  response = RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse.read(raw_response)
29
+ unless response.valid?
30
+ raise RubySMB::Error::InvalidPacket.new(
31
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
32
+ expected_cmd: RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest::COMMAND,
33
+ received_proto: response.smb_header.protocol,
34
+ received_cmd: response.smb_header.command
35
+ )
36
+ end
29
37
 
30
38
  unless response.status_code == WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW or response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
31
39
  raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
32
40
  end
33
41
 
34
- unless response.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_TRANSACTION
35
- raise RubySMB::Error::InvalidPacket, 'Not a TransResponse packet'
36
- end
37
42
  response
38
43
  end
39
44
 
@@ -39,11 +39,20 @@ module RubySMB
39
39
  # Disconnects this Tree from the current session
40
40
  #
41
41
  # @return [WindowsError::ErrorCode] the NTStatus sent back by the server.
42
+ # @raise [RubySMB::Error::InvalidPacket] if the response is not a TreeDisconnectResponse packet
42
43
  def disconnect!
43
44
  request = RubySMB::SMB1::Packet::TreeDisconnectRequest.new
44
45
  request = set_header_fields(request)
45
46
  raw_response = client.send_recv(request)
46
47
  response = RubySMB::SMB1::Packet::TreeDisconnectResponse.read(raw_response)
48
+ unless response.valid?
49
+ raise RubySMB::Error::InvalidPacket.new(
50
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
51
+ expected_cmd: RubySMB::SMB1::Packet::TreeDisconnectResponse::COMMAND,
52
+ received_proto: response.smb_header.protocol,
53
+ received_cmd: response.smb_header.command
54
+ )
55
+ end
47
56
  response.status_code
48
57
  end
49
58
 
@@ -113,8 +122,13 @@ module RubySMB
113
122
 
114
123
  raw_response = @client.send_recv(nt_create_andx_request)
115
124
  response = RubySMB::SMB1::Packet::NtCreateAndxResponse.read(raw_response)
116
- unless response.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_NT_CREATE_ANDX
117
- raise RubySMB::Error::InvalidPacket, 'Not a NtCreateAndxResponse packet'
125
+ unless response.valid?
126
+ raise RubySMB::Error::InvalidPacket.new(
127
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
128
+ expected_cmd: RubySMB::SMB1::Packet::NtCreateAndxResponse::COMMAND,
129
+ received_proto: response.smb_header.protocol,
130
+ received_cmd: response.smb_header.command
131
+ )
118
132
  end
119
133
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
120
134
  raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
@@ -140,6 +154,8 @@ module RubySMB
140
154
  # @param pattern [String] search pattern
141
155
  # @param type [Class] file information class
142
156
  # @return [Array] array of directory structures
157
+ # @raise [RubySMB::Error::InvalidPacket] if the response is not a Trans2 packet
158
+ # @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
143
159
  def list(directory: '\\', pattern: '*', unicode: true,
144
160
  type: RubySMB::SMB1::Packet::Trans2::FindInformationLevel::FindFileFullDirectoryInfo)
145
161
  find_first_request = RubySMB::SMB1::Packet::Trans2::FindFirst2Request.new
@@ -166,6 +182,17 @@ module RubySMB
166
182
 
167
183
  raw_response = client.send_recv(find_first_request)
168
184
  response = RubySMB::SMB1::Packet::Trans2::FindFirst2Response.read(raw_response)
185
+ unless response.valid?
186
+ raise RubySMB::Error::InvalidPacket.new(
187
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
188
+ expected_cmd: RubySMB::SMB1::Packet::Trans2::FindFirst2Response::COMMAND,
189
+ received_proto: response.smb_header.protocol,
190
+ received_cmd: response.smb_header.command
191
+ )
192
+ end
193
+ unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
194
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
195
+ end
169
196
 
170
197
  results = response.results(type, unicode: unicode)
171
198
 
@@ -190,6 +217,17 @@ module RubySMB
190
217
 
191
218
  raw_response = client.send_recv(find_next_request)
192
219
  response = RubySMB::SMB1::Packet::Trans2::FindNext2Response.read(raw_response)
220
+ unless response.valid?
221
+ raise RubySMB::Error::InvalidPacket.new(
222
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
223
+ expected_cmd: RubySMB::SMB1::Packet::Trans2::FindNext2Response::COMMAND,
224
+ received_proto: response.smb_header.protocol,
225
+ received_cmd: response.smb_header.command
226
+ )
227
+ end
228
+ unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
229
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
230
+ end
193
231
 
194
232
  results += response.results(type, unicode: unicode)
195
233
 
@@ -55,8 +55,13 @@ module RubySMB
55
55
  request.buffer = action.to_binary_s
56
56
  ioctl_raw_response = @tree.client.send_recv(request)
57
57
  ioctl_response = RubySMB::SMB2::Packet::IoctlResponse.read(ioctl_raw_response)
58
- unless ioctl_response.smb2_header.command == RubySMB::SMB2::Commands::IOCTL
59
- raise RubySMB::Error::InvalidPacket, 'Not a IoctlResponse packet'
58
+ unless ioctl_response.valid?
59
+ raise RubySMB::Error::InvalidPacket.new(
60
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
61
+ expected_cmd: RubySMB::SMB2::Packet::IoctlRequest::COMMAND,
62
+ received_proto: ioctl_response.smb2_header.protocol,
63
+ received_cmd: ioctl_response.smb2_header.command
64
+ )
60
65
  end
61
66
  unless ioctl_response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
62
67
  raise RubySMB::Error::UnexpectedStatusCode, ioctl_response.status_code.name
@@ -79,11 +79,24 @@ module RubySMB
79
79
  # Closes the handle to the remote file.
80
80
  #
81
81
  # @return [WindowsError::ErrorCode] the NTStatus code returned by the operation
82
+ # @raise [RubySMB::Error::InvalidPacket] if the response is not a CloseResponse packet
83
+ # @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
82
84
  def close
83
85
  close_request = set_header_fields(RubySMB::SMB2::Packet::CloseRequest.new)
84
86
  raw_response = tree.client.send_recv(close_request)
85
87
  response = RubySMB::SMB2::Packet::CloseResponse.read(raw_response)
86
- response.smb2_header.nt_status.to_nt_status
88
+ unless response.valid?
89
+ raise RubySMB::Error::InvalidPacket.new(
90
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
91
+ expected_cmd: RubySMB::SMB2::Packet::CloseResponse::COMMAND,
92
+ received_proto: response.smb2_header.protocol,
93
+ received_cmd: response.smb2_header.command
94
+ )
95
+ end
96
+ unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
97
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
98
+ end
99
+ response.status_code
87
100
  end
88
101
 
89
102
  # Read from the file, a specific number of bytes
@@ -93,6 +106,8 @@ module RubySMB
93
106
  # @param bytes [Integer] the number of bytes to read
94
107
  # @param offset [Integer] the byte offset in the file to start reading from
95
108
  # @return [String] the data read from the file
109
+ # @raise [RubySMB::Error::InvalidPacket] if the response is not a ReadResponse packet
110
+ # @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
96
111
  def read(bytes: size, offset: 0)
97
112
  atomic_read_size = if bytes > tree.client.server_max_read_size
98
113
  tree.client.server_max_read_size
@@ -103,6 +118,17 @@ module RubySMB
103
118
  read_request = read_packet(read_length: atomic_read_size, offset: offset)
104
119
  raw_response = tree.client.send_recv(read_request)
105
120
  response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
121
+ unless response.valid?
122
+ raise RubySMB::Error::InvalidPacket.new(
123
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
124
+ expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
125
+ received_proto: response.smb2_header.protocol,
126
+ received_cmd: response.smb2_header.command
127
+ )
128
+ end
129
+ unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
130
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
131
+ end
106
132
 
107
133
  data = response.buffer.to_binary_s
108
134
 
@@ -115,6 +141,17 @@ module RubySMB
115
141
  read_request = read_packet(read_length: atomic_read_size, offset: offset)
116
142
  raw_response = tree.client.send_recv(read_request)
117
143
  response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
144
+ unless response.valid?
145
+ raise RubySMB::Error::InvalidPacket.new(
146
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
147
+ expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
148
+ received_proto: response.smb2_header.protocol,
149
+ received_cmd: response.smb2_header.command
150
+ )
151
+ end
152
+ unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
153
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
154
+ end
118
155
 
119
156
  data << response.buffer.to_binary_s
120
157
  remaining_bytes -= atomic_read_size
@@ -138,10 +175,26 @@ module RubySMB
138
175
  read_request = read_packet(read_length: read_length, offset: offset)
139
176
  raw_response = tree.client.send_recv(read_request)
140
177
  response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
178
+ unless response.valid?
179
+ raise RubySMB::Error::InvalidPacket.new(
180
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
181
+ expected_cmd: RubySMB::SMB2::Packet::ReadResponse::COMMAND,
182
+ received_proto: response.smb2_header.protocol,
183
+ received_cmd: response.smb2_header.command
184
+ )
185
+ end
141
186
  if response.status_code == WindowsError::NTStatus::STATUS_PENDING
142
187
  sleep 1
143
188
  raw_response = tree.client.dispatcher.recv_packet
144
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
145
198
  elsif response.status_code != WindowsError::NTStatus::STATUS_SUCCESS
146
199
  raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
147
200
  end
@@ -151,9 +204,18 @@ module RubySMB
151
204
  # Delete a file on close
152
205
  #
153
206
  # @return [WindowsError::ErrorCode] the NTStatus Response code
207
+ # @raise [RubySMB::Error::InvalidPacket] if the response is not a SetInfoResponse packet
154
208
  def delete
155
209
  raw_response = tree.client.send_recv(delete_packet)
156
210
  response = RubySMB::SMB2::Packet::SetInfoResponse.read(raw_response)
211
+ unless response.valid?
212
+ raise RubySMB::Error::InvalidPacket.new(
213
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
214
+ expected_cmd: RubySMB::SMB2::Packet::SetInfoResponse::COMMAND,
215
+ received_proto: response.smb2_header.protocol,
216
+ received_cmd: response.smb2_header.command
217
+ )
218
+ end
157
219
  response.smb2_header.nt_status.to_nt_status
158
220
  end
159
221
 
@@ -182,6 +244,7 @@ module RubySMB
182
244
  # @param data [String] the data to write to the file
183
245
  # @param offset [Integer] the offset in the file to start writing from
184
246
  # @return [WindowsError::ErrorCode] the NTStatus code returned from the operation
247
+ # @raise [RubySMB::Error::InvalidPacket] if the response is not a WriteResponse packet
185
248
  def write(data:'', offset: 0)
186
249
  buffer = data.dup
187
250
  bytes = data.length
@@ -195,6 +258,14 @@ module RubySMB
195
258
  write_request = write_packet(data: buffer.slice!(0,atomic_write_size), offset: offset)
196
259
  raw_response = tree.client.send_recv(write_request)
197
260
  response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
261
+ unless response.valid?
262
+ raise RubySMB::Error::InvalidPacket.new(
263
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
264
+ expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
265
+ received_proto: response.smb2_header.protocol,
266
+ received_cmd: response.smb2_header.command
267
+ )
268
+ end
198
269
  status = response.smb2_header.nt_status.to_nt_status
199
270
 
200
271
  offset+= atomic_write_size
@@ -220,10 +291,26 @@ module RubySMB
220
291
  pkt = write_packet(data: data, offset: offset)
221
292
  raw_response = tree.client.send_recv(pkt)
222
293
  response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
294
+ unless response.valid?
295
+ raise RubySMB::Error::InvalidPacket.new(
296
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
297
+ expected_cmd: RubySMB::SMB2::Packet::WriteResponse::COMMAND,
298
+ received_proto: response.smb2_header.protocol,
299
+ received_cmd: response.smb2_header.command
300
+ )
301
+ end
223
302
  if response.status_code == WindowsError::NTStatus::STATUS_PENDING
224
303
  sleep 1
225
304
  raw_response = tree.client.dispatcher.recv_packet
226
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
227
314
  elsif response.status_code != WindowsError::NTStatus::STATUS_SUCCESS
228
315
  raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
229
316
  end
@@ -234,9 +321,18 @@ module RubySMB
234
321
  #
235
322
  # @param new_file_name [String] the new name
236
323
  # @return [WindowsError::ErrorCode] the NTStatus Response code
324
+ # @raise [RubySMB::Error::InvalidPacket] if the response is not a SetInfoResponse packet
237
325
  def rename(new_file_name)
238
326
  raw_response = tree.client.send_recv(rename_packet(new_file_name))
239
327
  response = RubySMB::SMB2::Packet::SetInfoResponse.read(raw_response)
328
+ unless response.valid?
329
+ raise RubySMB::Error::InvalidPacket.new(
330
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
331
+ expected_cmd: RubySMB::SMB2::Packet::SetInfoResponse::COMMAND,
332
+ received_proto: response.smb2_header.protocol,
333
+ received_cmd: response.smb2_header.command
334
+ )
335
+ end
240
336
  response.smb2_header.nt_status.to_nt_status
241
337
  end
242
338
 
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # An SMB2 Close Request Packet as defined in
5
5
  # [2.2.15 SMB2 CLOSE Request](https://msdn.microsoft.com/en-us/library/cc246523.aspx)
6
6
  class CloseRequest < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::CLOSE
8
+
7
9
  endian :little
8
10
 
9
11
  smb2_header :smb2_header
@@ -12,10 +14,6 @@ module RubySMB
12
14
  uint32 :reserved, label: 'Reserved Space'
13
15
  smb2_fileid :file_id, label: 'File ID'
14
16
 
15
- def initialize_instance
16
- super
17
- smb2_header.command = RubySMB::SMB2::Commands::CLOSE
18
- end
19
17
  end
20
18
  end
21
19
  end