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.
Files changed (200) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.travis.yml +3 -2
  5. data/Gemfile +6 -2
  6. data/README.md +35 -47
  7. data/examples/enum_registry_key.rb +28 -0
  8. data/examples/enum_registry_values.rb +30 -0
  9. data/examples/negotiate.rb +51 -8
  10. data/examples/pipes.rb +2 -1
  11. data/examples/read_file_encryption.rb +56 -0
  12. data/examples/read_registry_key_value.rb +32 -0
  13. data/lib/ruby_smb.rb +4 -1
  14. data/lib/ruby_smb/client.rb +233 -22
  15. data/lib/ruby_smb/client/authentication.rb +70 -33
  16. data/lib/ruby_smb/client/echo.rb +20 -2
  17. data/lib/ruby_smb/client/encryption.rb +62 -0
  18. data/lib/ruby_smb/client/negotiation.rb +172 -24
  19. data/lib/ruby_smb/client/signing.rb +19 -0
  20. data/lib/ruby_smb/client/tree_connect.rb +24 -18
  21. data/lib/ruby_smb/client/utils.rb +8 -7
  22. data/lib/ruby_smb/client/winreg.rb +46 -0
  23. data/lib/ruby_smb/crypto.rb +30 -0
  24. data/lib/ruby_smb/dcerpc.rb +38 -0
  25. data/lib/ruby_smb/dcerpc/bind.rb +2 -2
  26. data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
  27. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  28. data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
  29. data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
  30. data/lib/ruby_smb/dcerpc/request.rb +28 -9
  31. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
  32. data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
  33. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
  34. data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
  35. data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
  36. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
  37. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
  38. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
  39. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
  40. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
  41. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
  42. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
  43. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
  44. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
  45. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
  46. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
  47. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
  48. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
  49. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
  50. data/lib/ruby_smb/dispatcher/socket.rb +4 -3
  51. data/lib/ruby_smb/error.rb +68 -2
  52. data/lib/ruby_smb/generic_packet.rb +33 -4
  53. data/lib/ruby_smb/smb1/commands.rb +1 -1
  54. data/lib/ruby_smb/smb1/file.rb +66 -15
  55. data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
  56. data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
  57. data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
  58. data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
  59. data/lib/ruby_smb/smb1/packet/empty_packet.rb +10 -1
  60. data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
  61. data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
  62. data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
  63. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
  64. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
  65. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
  66. data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
  67. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
  68. data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
  69. data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
  70. data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
  71. data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
  72. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
  73. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
  74. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +3 -2
  75. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
  76. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +3 -2
  77. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
  78. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
  79. data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
  80. data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
  81. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
  82. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
  83. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
  84. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
  85. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
  86. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
  87. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
  88. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
  89. data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
  90. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
  91. data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
  92. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
  93. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
  94. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
  95. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
  96. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
  97. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
  98. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +3 -6
  99. data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
  100. data/lib/ruby_smb/smb1/pipe.rb +87 -6
  101. data/lib/ruby_smb/smb1/tree.rb +50 -3
  102. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
  103. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
  104. data/lib/ruby_smb/smb2/file.rb +103 -25
  105. data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
  106. data/lib/ruby_smb/smb2/packet.rb +2 -0
  107. data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
  108. data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
  109. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
  110. data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
  111. data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
  112. data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
  113. data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
  114. data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -3
  115. data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
  116. data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
  117. data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
  118. data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
  119. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -17
  120. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +52 -5
  121. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
  122. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
  123. data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
  124. data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
  125. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
  126. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
  127. data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
  128. data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
  129. data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
  130. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +93 -10
  131. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +10 -22
  132. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
  133. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
  134. data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
  135. data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
  136. data/lib/ruby_smb/smb2/pipe.rb +86 -12
  137. data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
  138. data/lib/ruby_smb/smb2/tree.rb +65 -21
  139. data/lib/ruby_smb/version.rb +1 -1
  140. data/ruby_smb.gemspec +5 -3
  141. data/spec/lib/ruby_smb/client_spec.rb +1612 -108
  142. data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
  143. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
  144. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
  145. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
  146. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
  147. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
  148. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
  149. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
  150. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
  151. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
  152. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
  153. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
  154. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
  155. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
  156. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
  157. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
  158. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
  159. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
  160. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
  161. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
  162. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
  163. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
  164. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
  165. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
  166. data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
  167. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +2 -2
  168. data/spec/lib/ruby_smb/error_spec.rb +59 -0
  169. data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
  170. data/spec/lib/ruby_smb/smb1/file_spec.rb +191 -2
  171. data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +68 -0
  172. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
  173. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
  174. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
  175. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
  176. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
  177. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
  178. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
  179. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +272 -149
  180. data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
  181. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
  182. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
  183. data/spec/lib/ruby_smb/smb2/file_spec.rb +323 -6
  184. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
  185. data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
  186. data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
  187. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
  188. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
  189. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
  190. data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
  191. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
  192. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -22
  193. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +286 -149
  194. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
  195. data/spec/lib/ruby_smb/smb2/tree_spec.rb +261 -2
  196. metadata +191 -83
  197. metadata.gz.sig +0 -0
  198. data/lib/ruby_smb/smb1/dcerpc.rb +0 -67
  199. data/lib/ruby_smb/smb2/dcerpc.rb +0 -70
  200. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +0 -37
@@ -30,6 +30,8 @@ module RubySMB
30
30
  require 'ruby_smb/smb2/packet/write_response'
31
31
  require 'ruby_smb/smb2/packet/ioctl_request'
32
32
  require 'ruby_smb/smb2/packet/ioctl_response'
33
+ require 'ruby_smb/smb2/packet/transform_header'
34
+ require 'ruby_smb/smb2/packet/compression_transform_header'
33
35
  end
34
36
  end
35
37
  end
@@ -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
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # An SMB2 Close Response Packet as defined in
5
5
  # [2.2.16 SMB2 CLOSE Response](https://msdn.microsoft.com/en-us/library/cc246524.aspx)
6
6
  class CloseResponse < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::CLOSE
8
+
7
9
  endian :little
8
10
 
9
11
  smb2_header :smb2_header
@@ -20,7 +22,6 @@ module RubySMB
20
22
 
21
23
  def initialize_instance
22
24
  super
23
- smb2_header.command = RubySMB::SMB2::Commands::CLOSE
24
25
  smb2_header.flags.reply = 1
25
26
  end
26
27
  end
@@ -0,0 +1,41 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Packet
4
+ # An SMB2 COMPRESSION_TRANSFORM_HEADER Packet as defined in
5
+ # [2.2.42 SMB2 COMPRESSION_TRANSFORM_HEADER](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/1d435f21-9a21-4f4c-828e-624a176cf2a0)
6
+ class CompressionTransformHeader < BinData::Record
7
+ endian :little
8
+
9
+ bit32 :protocol, label: 'Protocol ID Field', initial_value: 0xFC534D42
10
+ uint32 :original_compressed_segment_size, label: 'Original Compressed Segment Size'
11
+ uint16 :compression_algorithm, label: 'Compression Algorithm'
12
+ uint16 :flags, label: 'Flags'
13
+ uint32 :offset, label: 'Offset / Length'
14
+ end
15
+
16
+ # An SMB2 SMB2_COMPRESSION_TRANSFORM_HEADER_PAYLOAD Packet as defined in
17
+ # [2.2.42.1 SMB2_COMPRESSION_TRANSFORM_HEADER_PAYLOAD](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/8898e8e7-f1b2-47f5-a525-2ce5bad6db64)
18
+ class Smb2CompressionPayloadHeader < BinData::Record
19
+ endian :little
20
+ hide :reserved
21
+
22
+ uint16 :algorithm_id, label: 'Algorithm ID'
23
+ uint16 :reserved
24
+ uint32 :payload_length, label: 'Compressed Payload Length'
25
+ end
26
+
27
+ # An SMB2 SMB2_COMPRESSION_PATTERN_PAYLOAD_V1 Packet as defined in
28
+ # [2.2.42.2 SMB2_COMPRESSION_PATTERN_PAYLOAD_V1](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/f6859837-395a-4d0a-8971-1fc3919e2d09)
29
+ class Smb2CompressionPatternPayloadV1 < BinData::Record
30
+ endian :little
31
+ hide :reserved1, :reserved2
32
+
33
+ uint8 :pattern, label: 'Pattern'
34
+ uint8 :reserved1
35
+ uint16 :reserved2
36
+ uint32 :repetitions, label: 'Repetitions'
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # An SMB2 Create Request Packet as defined in
5
5
  # [2.2.13 SMB2 CREATE Request](https://msdn.microsoft.com/en-us/library/cc246502.aspx)
6
6
  class CreateRequest < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::CREATE
8
+
7
9
  require 'ruby_smb/smb1/bit_field/create_options'
8
10
 
9
11
  endian :little
@@ -44,10 +46,6 @@ module RubySMB
44
46
 
45
47
  array :context, label: 'Contexts', type: :create_context, read_until: :eof
46
48
 
47
- def initialize_instance
48
- super
49
- smb2_header.command = RubySMB::SMB2::Commands::CREATE
50
- end
51
49
  end
52
50
  end
53
51
  end
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # An SMB2 Create Response Packet as defined in
5
5
  # [2.2.14 SMB2 CREATE Response](https://msdn.microsoft.com/en-us/library/cc246512.aspx)
6
6
  class CreateResponse < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::CREATE
8
+
7
9
  endian :little
8
10
  smb2_header :smb2_header
9
11
  uint16 :structure_size, label: 'Structure Size', initial_value: 89
@@ -26,7 +28,6 @@ module RubySMB
26
28
 
27
29
  def initialize_instance
28
30
  super
29
- smb2_header.command = RubySMB::SMB2::Commands::CREATE
30
31
  smb2_header.flags.reply = 1
31
32
  end
32
33
  end
@@ -4,15 +4,13 @@ module RubySMB
4
4
  # An SMB2 Echo Request Packet as defined in
5
5
  # [2.2.28 SMB2 ECHO Request](https://msdn.microsoft.com/en-us/library/cc246540.aspx)
6
6
  class EchoRequest < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::ECHO
8
+
7
9
  endian :little
8
10
  smb2_header :smb2_header
9
11
  uint16 :structure_size, label: 'Structure Size', initial_value: 4
10
12
  uint16 :reserved
11
13
 
12
- def initialize_instance
13
- super
14
- smb2_header.command = RubySMB::SMB2::Commands::ECHO
15
- end
16
14
  end
17
15
  end
18
16
  end
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # An SMB2 Echo response Packet as defined in
5
5
  # [2.2.29 SMB2 ECHO Response](https://msdn.microsoft.com/en-us/library/cc246541.aspx)
6
6
  class EchoResponse < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::ECHO
8
+
7
9
  endian :little
8
10
  smb2_header :smb2_header
9
11
  uint16 :structure_size, label: 'Structure Size', initial_value: 4
@@ -11,7 +13,6 @@ module RubySMB
11
13
 
12
14
  def initialize_instance
13
15
  super
14
- smb2_header.command = RubySMB::SMB2::Commands::ECHO
15
16
  smb2_header.flags.reply = 1
16
17
  end
17
18
  end
@@ -1,12 +1,24 @@
1
1
  module RubySMB
2
2
  module SMB2
3
3
  module Packet
4
- # An SMB2 Error packet for when an incomplete response comes back
4
+ # This class represents an SMB2 Error Response Packet as defined in
5
+ # [2.2.2 SMB2 ERROR Response](https://msdn.microsoft.com/en-us/library/cc246530.aspx)
5
6
  class ErrorPacket < RubySMB::GenericPacket
7
+ attr_accessor :original_command
8
+
6
9
  endian :little
7
10
  smb2_header :smb2_header
8
- uint16 :structure_size, label: 'Structure Size', initial_value: 4
9
- uint8 :error_data
11
+ uint16 :structure_size, label: 'Structure Size', initial_value: 9
12
+ uint8 :error_context_count, label: 'ErrorContextCount'
13
+ uint8 :reserved
14
+ uint32 :byte_count, label: 'Byte Count of ErrorData'
15
+ string :error_data, label: 'Error Data', read_length: -> { byte_count }
16
+
17
+ def valid?
18
+ return smb2_header.protocol == RubySMB::SMB2::SMB2_PROTOCOL_ID &&
19
+ smb2_header.command == @original_command &&
20
+ structure_size == 9
21
+ end
10
22
  end
11
23
  end
12
24
  end
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # An SMB2 Ioctl Request Packet as defined in
5
5
  # [2.2.31 SMB2 IOCTL Request](https://msdn.microsoft.com/en-us/library/cc246545.aspx)
6
6
  class IoctlRequest < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::IOCTL
8
+
7
9
  endian :little
8
10
 
9
11
  smb2_header :smb2_header
@@ -30,11 +32,6 @@ module RubySMB
30
32
  uint32 :reserved2, label: 'Reserved Space'
31
33
  string :buffer, label: 'Input Buffer', read_length: -> { input_count + output_count }
32
34
 
33
- def initialize_instance
34
- super
35
- smb2_header.command = RubySMB::SMB2::Commands::IOCTL
36
- end
37
-
38
35
  # Calculates the value for the input_offset field.
39
36
  # If the input buffer is empty then this should be set to 0,
40
37
  # otherwise it should return the absolute offset of the input buffer.
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # An SMB2 Ioctl Response Packet as defined in
5
5
  # [2.2.32 SMB2 IOCTL Response](https://msdn.microsoft.com/en-us/library/cc246548.aspx)
6
6
  class IoctlResponse < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::IOCTL
8
+
7
9
  endian :little
8
10
 
9
11
  smb2_header :smb2_header
@@ -22,7 +24,6 @@ module RubySMB
22
24
  def initialize_instance
23
25
  super
24
26
  smb2_header.flags.reply = 1
25
- smb2_header.command = RubySMB::SMB2::Commands::IOCTL
26
27
  end
27
28
 
28
29
  def input_data
@@ -4,15 +4,13 @@ module RubySMB
4
4
  # An SMB2 LOGOFF Request Packet as defined in
5
5
  # [2.2.7 SMB2 LOGOFF Request](https://msdn.microsoft.com/en-us/library/cc246565.aspx)
6
6
  class LogoffRequest < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::LOGOFF
8
+
7
9
  endian :little
8
10
  smb2_header :smb2_header
9
11
  uint16 :structure_size, label: 'Structure Size', initial_value: 4
10
12
  uint16 :reserved, label: 'Reserved Space'
11
13
 
12
- def initialize_instance
13
- super
14
- smb2_header.command = RubySMB::SMB2::Commands::LOGOFF
15
- end
16
14
  end
17
15
  end
18
16
  end
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # An SMB2 LOGOFF Response Packet as defined in
5
5
  # [2.2.8 SMB2 LOGOFF Response](https://msdn.microsoft.com/en-us/library/cc246566.aspx)
6
6
  class LogoffResponse < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB2::Commands::LOGOFF
8
+
7
9
  endian :little
8
10
  smb2_header :smb2_header
9
11
  uint16 :structure_size, label: 'Structure Size', initial_value: 4
@@ -11,7 +13,6 @@ module RubySMB
11
13
 
12
14
  def initialize_instance
13
15
  super
14
- smb2_header.command = RubySMB::SMB2::Commands::LOGOFF
15
16
  smb2_header.flags.reply = 1
16
17
  end
17
18
  end
@@ -1,33 +1,39 @@
1
+ require 'ruby_smb/smb2/negotiate_context'
2
+
1
3
  module RubySMB
2
4
  module SMB2
3
5
  module Packet
4
6
  # An SMB2 NEGOTIATE Request packet as defined by
5
7
  # [2.2.3 SMB2 NEGOTIATE Request](https://msdn.microsoft.com/en-us/library/cc246543.aspx)
6
8
  class NegotiateRequest < RubySMB::GenericPacket
9
+ COMMAND = RubySMB::SMB2::Commands::NEGOTIATE
10
+
7
11
  endian :little
8
12
  smb2_header :smb2_header
9
- uint16 :structure_size, label: 'Structure Size', initial_value: 36
10
- uint16 :dialect_count, label: 'Dialect Count'
11
- smb2_security_mode :security_mode
12
- uint16 :reserved1, label: 'Reserved', initial_value: 0
13
- smb2_capabilities :capabilities
14
- string :client_guid, label: 'Client GUID', length: 16
15
- file_time :client_start_time, label: 'Client Start Time', initial_value: 0
16
- array :dialects, label: 'Dialects', type: :uint16, read_until: :eof
17
-
18
- def initialize_instance
19
- super
20
- smb2_header.command = RubySMB::SMB2::Commands::NEGOTIATE
13
+ uint16 :structure_size, label: 'Structure Size', initial_value: 36
14
+ uint16 :dialect_count, label: 'Dialect Count', initial_value: -> { dialects.size }
15
+ smb2_security_mode :security_mode, label: 'Security Mode'
16
+ uint16 :reserved1, label: 'Reserved', initial_value: 0
17
+ smb2_capabilities :capabilities, label: 'Capabilities'
18
+ string :client_guid, label: 'Client GUID', length: 16
19
+ struct :negotiate_context_info, label: 'Negotiate Context Info', onlyif: -> { has_negotiate_context? } do
20
+ uint32 :negotiate_context_offset, label: 'Negotiate Context Offset', initial_value: -> { negotiate_context_list.abs_offset }
21
+ uint16 :negotiate_context_count, label: 'Negotiate Context Count', initial_value: -> { negotiate_context_list.size }
22
+ uint16 :reserved2, label: 'Reserved', initial_value: 0
21
23
  end
24
+ file_time :client_start_time, label: 'Client Start Time', initial_value: 0, onlyif: -> { !has_negotiate_context? }
25
+ array :dialects, label: 'Dialects', type: :uint16, initial_length: -> { dialect_count }
26
+ string :pad, label: 'Padding', length: -> { pad_length(self.dialects) }, onlyif: -> { has_negotiate_context? }
27
+ array :negotiate_context_list, label: 'Negotiate Context List', type: :negotiate_context, onlyif: -> { has_negotiate_context? }, read_until: :eof
22
28
 
23
- # Adds a dialect to the Dialects array and increments the dialect count
29
+ # Adds a dialect to the Dialects array
24
30
  #
25
31
  # @param [Fixnum] the numeric code for the dialect you wish to add
26
32
  # @return [Array<Fixnum>] the array of all currently selected dialects
33
+ # @raise [ArgumentError] if the dialect is not an Integer
27
34
  def add_dialect(dialect)
28
- return ArgumentError, 'Must be a number' unless dialect.is_a? Integer
29
- self.dialect_count += 1
30
- dialects << dialect
35
+ raise ArgumentError, 'Must be a number' unless dialect.is_a? Integer
36
+ self.dialects << dialect
31
37
  end
32
38
 
33
39
  # Takes an array of dialects and sets it on the packet. Also updates
@@ -38,12 +44,40 @@ module RubySMB
38
44
  # @return [Array<Fixnum>] the current value of the dialects array
39
45
  def set_dialects(add_dialects = [])
40
46
  self.dialects = []
41
- self.dialect_count = 0
42
47
  add_dialects.each do |dialect|
43
48
  add_dialect(dialect)
44
49
  end
45
50
  dialects
46
51
  end
52
+
53
+ # Adds a Negotiate Context to the #negotiate_context_list
54
+ #
55
+ # @param [NegotiateContext] the Negotiate Context structure you wish to add
56
+ # @return [Array<Fixnum>] the array of all currently added Negotiate Contexts
57
+ # @raise [ArgumentError] if the dialect is not a NegotiateContext structure
58
+ def add_negotiate_context(nc)
59
+ raise ArgumentError, 'Must be a NegotiateContext' unless nc.is_a? NegotiateContext
60
+ previous_element = negotiate_context_list.last || negotiate_context_list
61
+ pad_length = pad_length(previous_element)
62
+ self.negotiate_context_list << nc
63
+ self.negotiate_context_list.last.pad = "\x00" * pad_length
64
+ self.negotiate_context_list
65
+ end
66
+
67
+
68
+ private
69
+
70
+ # Determines the correct length for the padding, so that the next
71
+ # field is 8-byte aligned.
72
+ def pad_length(prev_element)
73
+ offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 8
74
+ (8 - offset) % 8
75
+ end
76
+
77
+ # Return true if the dialect version requires Negotiate Contexts
78
+ def has_negotiate_context?
79
+ dialects.any? { |dialect| dialect.to_i == 0x0311 }
80
+ end
47
81
  end
48
82
  end
49
83
  end
@@ -1,16 +1,21 @@
1
+ require 'ruby_smb/smb2/negotiate_context'
2
+
1
3
  module RubySMB
2
4
  module SMB2
3
5
  module Packet
4
6
  # An SMB2 NEGOTIATE Response packet as defined by
5
7
  # [2.2.4 SMB2 NEGOTIATE Response](https://msdn.microsoft.com/en-us/library/cc246561.aspx)
6
8
  class NegotiateResponse < RubySMB::GenericPacket
9
+ COMMAND = RubySMB::SMB2::Commands::NEGOTIATE
10
+
7
11
  endian :little
8
12
  smb2_header :smb2_header
9
- uint16 :structure_size, label: 'Structure Size', initial_value: 65
13
+ uint16 :structure_size, label: 'Structure Size', initial_value: 65
10
14
  smb2_security_mode :security_mode
11
15
  uint16 :dialect_revision, label: 'Dialect Revision'
12
- uint16 :negotiate_context_count, label: 'Negotiate Context Count', initial_value: 0
13
- string :server_guid, label: 'Server GUID', length: 16
16
+ uint16 :negotiate_context_count, label: 'Negotiate Context Count', initial_value: -> { negotiate_context_list.size }, onlyif: -> { has_negotiate_context? }
17
+ uint16 :reserved1, label: 'Reserved', initial_value: 0, onlyif: -> { !has_negotiate_context? }
18
+ string :server_guid, label: 'Server GUID', length: 16
14
19
  smb2_capabilities :capabilities
15
20
  uint32 :max_transact_size, label: 'Max Transaction Size'
16
21
  uint32 :max_read_size, label: 'Max Read Size'
@@ -19,14 +24,56 @@ module RubySMB
19
24
  file_time :server_start_time, label: 'Server Start Time'
20
25
  uint16 :security_buffer_offset, label: 'Offset to Security Buffer'
21
26
  uint16 :security_buffer_length, label: 'Security Buffer Length', initial_value: -> { security_buffer.length }
22
- uint32 :negotiate_context_offset, label: 'Offset to Negotiate Context'
27
+ uint32 :negotiate_context_offset, label: 'Offset to Negotiate Context', onlyif: -> { has_negotiate_context? }
28
+ uint32 :reserved2, label: 'Reserved', initial_value: 0, onlyif: -> { !has_negotiate_context? }
23
29
  string :security_buffer, label: 'Security Buffer', read_length: :security_buffer_length
30
+ string :pad, label: 'Padding', length: -> { pad_length(self.security_buffer) }, onlyif: -> { has_negotiate_context? }
31
+ array :negotiate_context_list, label: 'Negotiate Context List', initial_length: -> { negotiate_context_count }, type: :negotiate_context, onlyif: -> { has_negotiate_context? }
24
32
 
25
33
  def initialize_instance
26
34
  super
27
- smb2_header.command = RubySMB::SMB2::Commands::NEGOTIATE
28
35
  smb2_header.flags.reply = 1
29
36
  end
37
+
38
+ # Find the first Negotiate Context structure that matches the given
39
+ # context type
40
+ #
41
+ # @param [Integer] the Negotiate Context structure you wish to add
42
+ # @return [NegotiateContext] the Negotiate Context structure or nil if
43
+ # not found
44
+ def find_negotiate_context(type)
45
+ negotiate_context_list.find { |nc| nc.context_type == type }
46
+ end
47
+
48
+ # Adds a Negotiate Context to the #negotiate_context_list
49
+ #
50
+ # @param [NegotiateContext] the Negotiate Context structure you wish to add
51
+ # @return [Array<Fixnum>] the array of all currently added Negotiate Contexts
52
+ # @raise [ArgumentError] if the dialect is not a NegotiateContext structure
53
+ def add_negotiate_context(nc)
54
+ raise ArgumentError, 'Must be a NegotiateContext' unless nc.is_a? NegotiateContext
55
+ previous_element = negotiate_context_list.last || negotiate_context_list
56
+ pad_length = pad_length(previous_element)
57
+ self.negotiate_context_list << nc
58
+ self.negotiate_context_list.last.pad = "\x00" * pad_length
59
+ self.negotiate_context_list
60
+ end
61
+
62
+
63
+ private
64
+
65
+ # Determines the correct length for the padding, so that the next
66
+ # field is 8-byte aligned.
67
+ def pad_length(prev_element)
68
+ offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 8
69
+ (8 - offset) % 8
70
+ end
71
+
72
+ # Return true if the dialect version requires Negotiate Contexts
73
+ def has_negotiate_context?
74
+ dialect_revision == 0x0311
75
+ end
76
+
30
77
  end
31
78
  end
32
79
  end