ruby_smb 0.0.18 → 0.0.19

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 (298) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +247 -7
  5. data/examples/anonymous_auth.rb +6 -3
  6. data/examples/append_file.rb +40 -0
  7. data/examples/authenticate.rb +12 -7
  8. data/examples/delete_file.rb +40 -0
  9. data/examples/list_directory.rb +45 -0
  10. data/examples/negotiate.rb +0 -1
  11. data/examples/negotiate_with_netbios_service.rb +36 -0
  12. data/examples/net_share_enum_all.rb +30 -0
  13. data/examples/read_file.rb +39 -0
  14. data/examples/rename_file.rb +41 -0
  15. data/examples/tree_connect.rb +2 -4
  16. data/examples/write_file.rb +40 -0
  17. data/lib/ruby_smb.rb +5 -0
  18. data/lib/ruby_smb/client.rb +196 -43
  19. data/lib/ruby_smb/client/authentication.rb +89 -48
  20. data/lib/ruby_smb/client/echo.rb +1 -4
  21. data/lib/ruby_smb/client/negotiation.rb +46 -45
  22. data/lib/ruby_smb/client/signing.rb +9 -16
  23. data/lib/ruby_smb/client/tree_connect.rb +8 -13
  24. data/lib/ruby_smb/client/utils.rb +79 -0
  25. data/lib/ruby_smb/dcerpc.rb +30 -0
  26. data/lib/ruby_smb/dcerpc/bind.rb +60 -0
  27. data/lib/ruby_smb/dcerpc/handle.rb +60 -0
  28. data/lib/ruby_smb/dcerpc/ndr.rb +41 -0
  29. data/lib/ruby_smb/dcerpc/request.rb +43 -0
  30. data/lib/ruby_smb/dcerpc/response.rb +46 -0
  31. data/lib/ruby_smb/dcerpc/srvsvc.rb +17 -0
  32. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +93 -0
  33. data/lib/ruby_smb/dcerpc/uuid.rb +28 -0
  34. data/lib/ruby_smb/dispatcher.rb +7 -3
  35. data/lib/ruby_smb/dispatcher/base.rb +23 -14
  36. data/lib/ruby_smb/dispatcher/socket.rb +71 -51
  37. data/lib/ruby_smb/dispositions.rb +32 -0
  38. data/lib/ruby_smb/error.rb +24 -18
  39. data/lib/ruby_smb/field.rb +5 -2
  40. data/lib/ruby_smb/field/extended_attribute_flag.rb +1 -1
  41. data/lib/ruby_smb/field/file_time.rb +3 -1
  42. data/lib/ruby_smb/field/security_descriptor.rb +6 -6
  43. data/lib/ruby_smb/field/smb2_fileid.rb +11 -0
  44. data/lib/ruby_smb/field/smb_fea.rb +3 -3
  45. data/lib/ruby_smb/field/smb_fea_list.rb +3 -3
  46. data/lib/ruby_smb/field/smb_gea.rb +12 -0
  47. data/lib/ruby_smb/field/smb_gea_list.rb +13 -0
  48. data/lib/ruby_smb/field/string16.rb +14 -0
  49. data/lib/ruby_smb/field/stringz16.rb +3 -7
  50. data/lib/ruby_smb/field/utime.rb +11 -10
  51. data/lib/ruby_smb/fscc.rb +12 -0
  52. data/lib/ruby_smb/fscc/control_codes.rb +26 -0
  53. data/lib/ruby_smb/{field → fscc}/ea_info_array.rb +12 -14
  54. data/lib/ruby_smb/fscc/file_attributes.rb +29 -0
  55. data/lib/ruby_smb/{field → fscc}/file_full_ea_info.rb +5 -5
  56. data/lib/ruby_smb/fscc/file_information.rb +60 -0
  57. data/lib/ruby_smb/fscc/file_information/file_both_directory_information.rb +29 -0
  58. data/lib/ruby_smb/fscc/file_information/file_directory_information.rb +25 -0
  59. data/lib/ruby_smb/fscc/file_information/file_disposition_information.rb +15 -0
  60. data/lib/ruby_smb/fscc/file_information/file_full_directory_information.rb +26 -0
  61. data/lib/ruby_smb/fscc/file_information/file_id_both_directory_information.rb +31 -0
  62. data/lib/ruby_smb/fscc/file_information/file_id_full_directory_information.rb +28 -0
  63. data/lib/ruby_smb/fscc/file_information/file_names_information.rb +18 -0
  64. data/lib/ruby_smb/fscc/file_information/file_rename_information.rb +44 -0
  65. data/lib/ruby_smb/generic_packet.rb +40 -18
  66. data/lib/ruby_smb/gss.rb +49 -56
  67. data/lib/ruby_smb/impersonation_levels.rb +7 -2
  68. data/lib/ruby_smb/nbss.rb +16 -0
  69. data/lib/ruby_smb/nbss/negative_session_response.rb +30 -0
  70. data/lib/ruby_smb/nbss/session_header.rb +13 -0
  71. data/lib/ruby_smb/nbss/session_request.rb +13 -0
  72. data/lib/ruby_smb/smb1.rb +20 -17
  73. data/lib/ruby_smb/smb1/bit_field.rb +3 -0
  74. data/lib/ruby_smb/smb1/bit_field/create_options.rb +5 -5
  75. data/lib/ruby_smb/smb1/bit_field/file_status_flags.rb +18 -0
  76. data/lib/ruby_smb/smb1/bit_field/open2_access_mode.rb +11 -11
  77. data/lib/ruby_smb/smb1/bit_field/open2_open_mode.rb +1 -1
  78. data/lib/ruby_smb/smb1/bit_field/optional_support.rb +0 -1
  79. data/lib/ruby_smb/smb1/bit_field/security_flags.rb +15 -0
  80. data/lib/ruby_smb/smb1/bit_field/share_access.rb +2 -3
  81. data/lib/ruby_smb/smb1/bit_field/smb_ext_file_attributes.rb +21 -24
  82. data/lib/ruby_smb/smb1/bit_field/smb_file_attributes.rb +1 -1
  83. data/lib/ruby_smb/smb1/commands.rb +5 -0
  84. data/lib/ruby_smb/smb1/create_actions.rb +3 -5
  85. data/lib/ruby_smb/smb1/file.rb +289 -0
  86. data/lib/ruby_smb/smb1/oplock_levels.rb +2 -4
  87. data/lib/ruby_smb/smb1/packet.rb +10 -0
  88. data/lib/ruby_smb/smb1/packet/close_request.rb +31 -0
  89. data/lib/ruby_smb/smb1/packet/close_response.rb +28 -0
  90. data/lib/ruby_smb/smb1/packet/echo_request.rb +5 -7
  91. data/lib/ruby_smb/smb1/packet/echo_response.rb +5 -7
  92. data/lib/ruby_smb/smb1/packet/empty_packet.rb +1 -2
  93. data/lib/ruby_smb/smb1/packet/logoff_request.rb +1 -4
  94. data/lib/ruby_smb/smb1/packet/logoff_response.rb +1 -4
  95. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +22 -0
  96. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +22 -0
  97. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +62 -0
  98. data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +66 -0
  99. data/lib/ruby_smb/smb1/packet/nt_trans.rb +1 -2
  100. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +19 -13
  101. data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +8 -10
  102. data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +11 -11
  103. data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +10 -10
  104. data/lib/ruby_smb/smb1/packet/nt_trans/subcommands.rb +8 -1
  105. data/lib/ruby_smb/smb1/packet/read_andx_request.rb +84 -0
  106. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +47 -0
  107. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -6
  108. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +1 -4
  109. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -6
  110. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -4
  111. data/lib/ruby_smb/smb1/packet/trans2.rb +8 -2
  112. data/lib/ruby_smb/smb1/packet/trans2/data_block.rb +6 -7
  113. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +77 -0
  114. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +87 -0
  115. data/lib/ruby_smb/smb1/packet/trans2/find_information_level.rb +32 -0
  116. data/lib/ruby_smb/smb1/packet/trans2/find_information_level/find_file_full_directory_info.rb +45 -0
  117. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +77 -0
  118. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +86 -0
  119. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +10 -10
  120. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +10 -12
  121. data/lib/ruby_smb/smb1/packet/trans2/request.rb +15 -17
  122. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +8 -10
  123. data/lib/ruby_smb/smb1/packet/trans2/response.rb +11 -13
  124. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +66 -0
  125. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +57 -0
  126. data/lib/ruby_smb/smb1/packet/trans2/subcommands.rb +5 -2
  127. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +4 -6
  128. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +5 -7
  129. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
  130. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -4
  131. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +68 -0
  132. data/lib/ruby_smb/smb1/packet/write_andx_response.rb +35 -0
  133. data/lib/ruby_smb/smb1/resource_type.rb +18 -0
  134. data/lib/ruby_smb/smb1/tree.rb +188 -5
  135. data/lib/ruby_smb/smb2.rb +16 -11
  136. data/lib/ruby_smb/smb2/bit_field.rb +1 -0
  137. data/lib/ruby_smb/smb2/bit_field/file_access_mask.rb +1 -1
  138. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +1 -2
  139. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +4 -6
  140. data/lib/ruby_smb/smb2/create_context.rb +29 -0
  141. data/lib/ruby_smb/smb2/file.rb +251 -0
  142. data/lib/ruby_smb/smb2/info_type.rb +21 -0
  143. data/lib/ruby_smb/smb2/packet.rb +16 -0
  144. data/lib/ruby_smb/smb2/packet/close_request.rb +22 -0
  145. data/lib/ruby_smb/smb2/packet/close_response.rb +29 -0
  146. data/lib/ruby_smb/smb2/packet/create_request.rb +54 -0
  147. data/lib/ruby_smb/smb2/packet/create_response.rb +35 -0
  148. data/lib/ruby_smb/smb2/packet/echo_request.rb +1 -3
  149. data/lib/ruby_smb/smb2/packet/echo_response.rb +1 -3
  150. data/lib/ruby_smb/smb2/packet/error_packet.rb +1 -3
  151. data/lib/ruby_smb/smb2/packet/ioctl_request.rb +54 -0
  152. data/lib/ruby_smb/smb2/packet/ioctl_response.rb +39 -0
  153. data/lib/ruby_smb/smb2/packet/logoff_request.rb +1 -4
  154. data/lib/ruby_smb/smb2/packet/logoff_response.rb +1 -4
  155. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +1 -1
  156. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +1 -1
  157. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +35 -0
  158. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +45 -0
  159. data/lib/ruby_smb/smb2/packet/read_request.rb +30 -0
  160. data/lib/ruby_smb/smb2/packet/read_response.rb +26 -0
  161. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
  162. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +4 -7
  163. data/lib/ruby_smb/smb2/packet/set_info_request.rb +58 -0
  164. data/lib/ruby_smb/smb2/packet/set_info_response.rb +20 -0
  165. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +3 -4
  166. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +5 -9
  167. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +1 -4
  168. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +1 -4
  169. data/lib/ruby_smb/smb2/packet/write_request.rb +29 -0
  170. data/lib/ruby_smb/smb2/packet/write_response.rb +26 -0
  171. data/lib/ruby_smb/smb2/tree.rb +163 -7
  172. data/lib/ruby_smb/version.rb +1 -1
  173. data/spec/lib/ruby_smb/client_spec.rb +459 -120
  174. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +14 -0
  175. data/spec/lib/ruby_smb/dcerpc/handle_spec.rb +31 -0
  176. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +21 -0
  177. data/spec/lib/ruby_smb/dcerpc/response_spec.rb +15 -0
  178. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +13 -0
  179. data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +12 -0
  180. data/spec/lib/ruby_smb/dispatcher/base_spec.rb +26 -0
  181. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +118 -18
  182. data/spec/lib/ruby_smb/field/extended_attribute_flag_spec.rb +0 -3
  183. data/spec/lib/ruby_smb/field/file_time_spec.rb +4 -2
  184. data/spec/lib/ruby_smb/field/security_descriptor.rb +0 -1
  185. data/spec/lib/ruby_smb/field/smb2_fileid_spec.rb +10 -0
  186. data/spec/lib/ruby_smb/field/smb_fea_list_spec.rb +3 -5
  187. data/spec/lib/ruby_smb/field/smb_gea_list_spec.rb +37 -0
  188. data/spec/lib/ruby_smb/field/smb_gea_spec.rb +22 -0
  189. data/spec/lib/ruby_smb/field/stringz16_spec.rb +7 -9
  190. data/spec/lib/ruby_smb/field/utime_spec.rb +4 -2
  191. data/spec/lib/ruby_smb/{field → fscc}/ea_info_array_spec.rb +7 -9
  192. data/spec/lib/ruby_smb/{field → fscc}/file_full_ea_info_spec.rb +2 -3
  193. data/spec/lib/ruby_smb/fscc/file_information/file_both_directory_information_spec.rb +71 -0
  194. data/spec/lib/ruby_smb/fscc/file_information/file_directory_information_spec.rb +68 -0
  195. data/spec/lib/ruby_smb/fscc/file_information/file_disposition_information_spec.rb +26 -0
  196. data/spec/lib/ruby_smb/fscc/file_information/file_full_directory_information_spec.rb +69 -0
  197. data/spec/lib/ruby_smb/fscc/file_information/file_id_both_directory_information_spec.rb +72 -0
  198. data/spec/lib/ruby_smb/fscc/file_information/file_id_full_directory_information_spec.rb +70 -0
  199. data/spec/lib/ruby_smb/fscc/file_information/file_names_information_spec.rb +41 -0
  200. data/spec/lib/ruby_smb/fscc/file_information/file_rename_information_spec.rb +133 -0
  201. data/spec/lib/ruby_smb/fscc/fscc_file_attributes_spec.rb +143 -0
  202. data/spec/lib/ruby_smb/generic_packet_spec.rb +46 -21
  203. data/spec/lib/ruby_smb/nbss/negative_session_response_spec.rb +29 -0
  204. data/spec/lib/ruby_smb/nbss/session_header_spec.rb +30 -0
  205. data/spec/lib/ruby_smb/nbss/session_request_spec.rb +30 -0
  206. data/spec/lib/ruby_smb/smb1/bit_field/create_options_spec.rb +9 -1
  207. data/spec/lib/ruby_smb/smb1/bit_field/directory_access_mask_spec.rb +0 -2
  208. data/spec/lib/ruby_smb/smb1/bit_field/file_access_mask_spec.rb +0 -2
  209. data/spec/lib/ruby_smb/smb1/bit_field/file_status_flags_spec.rb +35 -0
  210. data/spec/lib/ruby_smb/smb1/bit_field/open2_access_mode_spec.rb +1 -3
  211. data/spec/lib/ruby_smb/smb1/bit_field/open2_flags_spec.rb +0 -2
  212. data/spec/lib/ruby_smb/smb1/bit_field/open2_open_mode_spec.rb +0 -1
  213. data/spec/lib/ruby_smb/smb1/bit_field/optional_support_spec.rb +0 -1
  214. data/spec/lib/ruby_smb/smb1/bit_field/security_flags_spec.rb +26 -0
  215. data/spec/lib/ruby_smb/smb1/bit_field/share_access_spec.rb +0 -3
  216. data/spec/lib/ruby_smb/smb1/bit_field/smb_ext_file_attributes_spec.rb +20 -39
  217. data/spec/lib/ruby_smb/smb1/bit_field/smb_file_attributes_spec.rb +0 -6
  218. data/spec/lib/ruby_smb/smb1/bit_field/smb_nmpipe_status_spec.rb +0 -2
  219. data/spec/lib/ruby_smb/smb1/bit_field/trans2_flags_spec.rb +0 -2
  220. data/spec/lib/ruby_smb/smb1/bit_field/tree_connect_flags_spec.rb +0 -2
  221. data/spec/lib/ruby_smb/smb1/file_spec.rb +469 -0
  222. data/spec/lib/ruby_smb/smb1/packet/close_request_spec.rb +54 -0
  223. data/spec/lib/ruby_smb/smb1/packet/close_response_spec.rb +45 -0
  224. data/spec/lib/ruby_smb/smb1/packet/echo_request_spec.rb +1 -4
  225. data/spec/lib/ruby_smb/smb1/packet/echo_response_spec.rb +1 -4
  226. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +1 -3
  227. data/spec/lib/ruby_smb/smb1/packet/logoff_request_spec.rb +1 -4
  228. data/spec/lib/ruby_smb/smb1/packet/logoff_response_spec.rb +1 -4
  229. data/spec/lib/ruby_smb/smb1/packet/negotiate_request_spec.rb +1 -1
  230. data/spec/lib/ruby_smb/smb1/packet/negotiate_response_extended_spec.rb +37 -0
  231. data/spec/lib/ruby_smb/smb1/packet/negotiate_response_spec.rb +37 -0
  232. data/spec/lib/ruby_smb/smb1/packet/nt_create_andx_request_spec.rb +151 -0
  233. data/spec/lib/ruby_smb/smb1/packet/nt_create_andx_response_spec.rb +157 -0
  234. data/spec/lib/ruby_smb/smb1/packet/nt_trans/create_request_spec.rb +13 -6
  235. data/spec/lib/ruby_smb/smb1/packet/nt_trans/create_response_spec.rb +1 -7
  236. data/spec/lib/ruby_smb/smb1/packet/nt_trans/request_spec.rb +1 -6
  237. data/spec/lib/ruby_smb/smb1/packet/nt_trans/response_spec.rb +1 -5
  238. data/spec/lib/ruby_smb/smb1/packet/read_andx_request_spec.rb +149 -0
  239. data/spec/lib/ruby_smb/smb1/packet/read_andx_response_spec.rb +93 -0
  240. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +1 -5
  241. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +1 -5
  242. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +3 -8
  243. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +2 -4
  244. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_request_spec.rb +180 -0
  245. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +104 -0
  246. data/spec/lib/ruby_smb/smb1/packet/trans2/find_information_level/find_file_full_directory_info_spec.rb +128 -0
  247. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_request_spec.rb +174 -0
  248. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +102 -0
  249. data/spec/lib/ruby_smb/smb1/packet/trans2/open2_request_spec.rb +1 -6
  250. data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +2 -7
  251. data/spec/lib/ruby_smb/smb1/packet/trans2/request_secondary_spec.rb +1 -5
  252. data/spec/lib/ruby_smb/smb1/packet/trans2/request_spec.rb +1 -5
  253. data/spec/lib/ruby_smb/smb1/packet/trans2/response_spec.rb +1 -4
  254. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_request_spec.rb +98 -0
  255. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +56 -0
  256. data/spec/lib/ruby_smb/smb1/packet/tree_connect_request_spec.rb +1 -5
  257. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +1 -6
  258. data/spec/lib/ruby_smb/smb1/packet/tree_disconnect_request_spec.rb +1 -4
  259. data/spec/lib/ruby_smb/smb1/packet/tree_disconnect_response_spec.rb +1 -4
  260. data/spec/lib/ruby_smb/smb1/packet/write_andx_request_spec.rb +148 -0
  261. data/spec/lib/ruby_smb/smb1/packet/write_andx_response_spec.rb +54 -0
  262. data/spec/lib/ruby_smb/smb1/tree_spec.rb +409 -7
  263. data/spec/lib/ruby_smb/smb2/bit_field/directory_access_mask_spec.rb +0 -2
  264. data/spec/lib/ruby_smb/smb2/bit_field/file_access_mask_spec.rb +0 -2
  265. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +1 -1
  266. data/spec/lib/ruby_smb/smb2/bit_field/share_capabilities_spec.rb +0 -1
  267. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +0 -2
  268. data/spec/lib/ruby_smb/smb2/create_context_spec.rb +42 -0
  269. data/spec/lib/ruby_smb/smb2/file_spec.rb +233 -0
  270. data/spec/lib/ruby_smb/smb2/packet/close_request_spec.rb +40 -0
  271. data/spec/lib/ruby_smb/smb2/packet/close_response_spec.rb +40 -0
  272. data/spec/lib/ruby_smb/smb2/packet/create_request_spec.rb +101 -0
  273. data/spec/lib/ruby_smb/smb2/packet/create_response_spec.rb +64 -0
  274. data/spec/lib/ruby_smb/smb2/packet/echo_request_spec.rb +1 -3
  275. data/spec/lib/ruby_smb/smb2/packet/echo_response_spec.rb +1 -3
  276. data/spec/lib/ruby_smb/smb2/packet/ioctl_request_spec.rb +48 -0
  277. data/spec/lib/ruby_smb/smb2/packet/logoff_request_spec.rb +1 -3
  278. data/spec/lib/ruby_smb/smb2/packet/logoff_response_spec.rb +1 -3
  279. data/spec/lib/ruby_smb/smb2/packet/query_directory_request_spec.rb +80 -0
  280. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +64 -0
  281. data/spec/lib/ruby_smb/smb2/packet/read_request_spec.rb +43 -0
  282. data/spec/lib/ruby_smb/smb2/packet/read_response_spec.rb +50 -0
  283. data/spec/lib/ruby_smb/smb2/packet/session_setup_request_spec.rb +3 -4
  284. data/spec/lib/ruby_smb/smb2/packet/session_setup_response_spec.rb +2 -3
  285. data/spec/lib/ruby_smb/smb2/packet/set_info_request_spec.rb +205 -0
  286. data/spec/lib/ruby_smb/smb2/packet/set_info_response_spec.rb +32 -0
  287. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +3 -5
  288. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +1 -2
  289. data/spec/lib/ruby_smb/smb2/packet/tree_disconnect_request_spec.rb +1 -3
  290. data/spec/lib/ruby_smb/smb2/packet/tree_disconnect_response_spec.rb +1 -3
  291. data/spec/lib/ruby_smb/smb2/packet/write_request_spec.rb +51 -0
  292. data/spec/lib/ruby_smb/smb2/packet/write_response_spec.rb +38 -0
  293. data/spec/lib/ruby_smb/smb2/tree_spec.rb +191 -5
  294. data/spec/spec_helper.rb +1 -1
  295. metadata +195 -12
  296. metadata.gz.sig +0 -0
  297. data/lib/ruby_smb/smb1/dispositions.rb +0 -36
  298. data/spec/lib/ruby_smb/dispatcher/dispatcher_base_spec.rb +0 -22
@@ -0,0 +1,148 @@
1
+ RSpec.describe RubySMB::SMB1::Packet::WriteAndxRequest do
2
+ subject(:packet) { described_class.new }
3
+
4
+ describe '#smb_header' do
5
+ subject(:header) { packet.smb_header }
6
+
7
+ it 'is a standard SMB Header' do
8
+ expect(header).to be_a RubySMB::SMB1::SMBHeader
9
+ end
10
+
11
+ it 'should have the command set to SMB_COM_WRITE_ANDX' do
12
+ expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
13
+ end
14
+
15
+ it 'should not have the response flag set' do
16
+ expect(header.flags.reply).to eq 0
17
+ end
18
+ end
19
+
20
+ describe '#parameter_block' do
21
+ subject(:parameter_block) { packet.parameter_block }
22
+
23
+ it 'is a standard ParameterBlock' do
24
+ expect(parameter_block).to be_a RubySMB::SMB1::ParameterBlock
25
+ end
26
+
27
+ it 'is little endian' do
28
+ expect(parameter_block.get_parameter(:endian).endian).to eq :little
29
+ end
30
+
31
+ describe '#word_count' do
32
+ it 'is set to the correct default value' do
33
+ expect(parameter_block.word_count).to eq(0x0C)
34
+ end
35
+ end
36
+
37
+ it { is_expected.to respond_to :andx_block }
38
+ it { is_expected.to respond_to :fid }
39
+ it { is_expected.to respond_to :offset }
40
+ it { is_expected.to respond_to :timeout }
41
+ it { is_expected.to respond_to :write_mode }
42
+ it { is_expected.to respond_to :remaining }
43
+ it { is_expected.to respond_to :data_length_high }
44
+ it { is_expected.to respond_to :data_length }
45
+ it { is_expected.to respond_to :data_offset }
46
+ it { is_expected.to respond_to :offset_high }
47
+
48
+ describe '#andx_block' do
49
+ it 'is a AndXBlock struct' do
50
+ expect(parameter_block.andx_block).to be_a RubySMB::SMB1::AndXBlock
51
+ end
52
+ end
53
+
54
+ describe '#write_mode' do
55
+ subject(:write_mode) { parameter_block.write_mode }
56
+
57
+ it { is_expected.to respond_to :msg_start }
58
+ it { is_expected.to respond_to :raw_mode }
59
+ it { is_expected.to respond_to :read_bytes_available }
60
+ it { is_expected.to respond_to :writethrough_mode }
61
+
62
+ it 'is little endian' do
63
+ expect(write_mode.get_parameter(:endian).endian).to eq :little
64
+ end
65
+
66
+ describe '#msg_start' do
67
+ it 'is a 1-bit flag' do
68
+ expect(write_mode.msg_start).to be_a BinData::Bit1
69
+ end
70
+
71
+ it_behaves_like 'bit field with one flag set', :msg_start, 'v', 0x0008
72
+ end
73
+
74
+ describe '#raw_mode' do
75
+ it 'is a 1-bit flag' do
76
+ expect(write_mode.raw_mode).to be_a BinData::Bit1
77
+ end
78
+
79
+ it_behaves_like 'bit field with one flag set', :raw_mode, 'v', 0x0004
80
+ end
81
+
82
+ describe '#read_bytes_available' do
83
+ it 'is a 1-bit flag' do
84
+ expect(write_mode.read_bytes_available).to be_a BinData::Bit1
85
+ end
86
+
87
+ it_behaves_like 'bit field with one flag set', :read_bytes_available, 'v', 0x0002
88
+ end
89
+
90
+ describe '#writethrough_mode' do
91
+ it 'is a 1-bit flag' do
92
+ expect(write_mode.writethrough_mode).to be_a BinData::Bit1
93
+ end
94
+
95
+ it_behaves_like 'bit field with one flag set', :writethrough_mode, 'v', 0x0001
96
+ end
97
+ end
98
+
99
+ describe '#offset_high' do
100
+ it 'exists when word_count is 0x0E' do
101
+ parameter_block.word_count = 0x0E
102
+ expect(parameter_block.offset_high?).to be true
103
+ end
104
+
105
+ it 'does not exist when word_count is 0x0C' do
106
+ parameter_block.word_count = 0x0C
107
+ expect(parameter_block.offset_high?).to be false
108
+ end
109
+ end
110
+ end
111
+
112
+ describe '#data_block' do
113
+ subject(:data_block) { packet.data_block }
114
+
115
+ it 'is a standard DataBlock' do
116
+ expect(data_block).to be_a RubySMB::SMB1::DataBlock
117
+ end
118
+
119
+ it { is_expected.to respond_to :pad }
120
+ it { is_expected.to respond_to :data }
121
+ end
122
+
123
+ describe '#set_64_bit_offset' do
124
+ it 'sets the #word_count field to 0x0E when passing true' do
125
+ packet.parameter_block.word_count = 0
126
+ packet.set_64_bit_offset(true)
127
+ expect(packet.parameter_block.word_count).to eq(0x0E)
128
+ end
129
+
130
+ it 'sets the #word_count field to 0x0C when passing false' do
131
+ packet.parameter_block.word_count = 0
132
+ packet.set_64_bit_offset(false)
133
+ expect(packet.parameter_block.word_count).to eq(0x0C)
134
+ end
135
+
136
+ it 'raises an exception when the value is a String' do
137
+ expect { packet.set_64_bit_offset('true') }.to raise_error(ArgumentError)
138
+ end
139
+
140
+ it 'raises an exception when the value is a Numeric' do
141
+ expect { packet.set_64_bit_offset(1) }.to raise_error(ArgumentError)
142
+ end
143
+
144
+ it 'raises an exception when the value is a Symbol' do
145
+ expect { packet.set_64_bit_offset(:true) }.to raise_error(ArgumentError)
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,54 @@
1
+ RSpec.describe RubySMB::SMB1::Packet::WriteAndxResponse do
2
+ subject(:packet) { described_class.new }
3
+
4
+ describe '#smb_header' do
5
+ subject(:header) { packet.smb_header }
6
+
7
+ it 'is a standard SMB Header' do
8
+ expect(header).to be_a RubySMB::SMB1::SMBHeader
9
+ end
10
+
11
+ it 'should have the command set to SMB_COM_WRITE_ANDX' do
12
+ expect(header.command).to eq RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
13
+ end
14
+
15
+ it 'should have the response flag set' do
16
+ expect(header.flags.reply).to eq 1
17
+ end
18
+ end
19
+
20
+ describe '#parameter_block' do
21
+ subject(:parameter_block) { packet.parameter_block }
22
+
23
+ it 'is a standard ParameterBlock' do
24
+ expect(parameter_block).to be_a RubySMB::SMB1::ParameterBlock
25
+ end
26
+
27
+ it 'is little endian' do
28
+ expect(parameter_block.get_parameter(:endian).endian).to eq :little
29
+ end
30
+
31
+ it { is_expected.to respond_to :andx_block }
32
+ it { is_expected.to respond_to :count_low }
33
+ it { is_expected.to respond_to :available }
34
+ it { is_expected.to respond_to :count_high }
35
+
36
+ describe '#andx_block' do
37
+ it 'is a AndXBlock struct' do
38
+ expect(parameter_block.andx_block).to be_a RubySMB::SMB1::AndXBlock
39
+ end
40
+ end
41
+ end
42
+
43
+ describe '#data_block' do
44
+ subject(:data_block) { packet.data_block }
45
+
46
+ it 'is a standard DataBlock' do
47
+ expect(data_block).to be_a RubySMB::SMB1::DataBlock
48
+ end
49
+
50
+ it 'should be empty' do
51
+ expect(data_block.byte_count).to eq(0)
52
+ end
53
+ end
54
+ end
@@ -1,21 +1,26 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RubySMB::SMB1::Tree do
4
- let(:sock) { double("Socket", peeraddr: '192.168.1.5' ) }
4
+ let(:ip) { '1.2.3.4' }
5
+ let(:sock) { double('Socket', peeraddr: ip) }
5
6
  let(:dispatcher) { RubySMB::Dispatcher::Socket.new(sock) }
6
7
 
7
8
  let(:client) { RubySMB::Client.new(dispatcher, username: 'msfadmin', password: 'msfadmin') }
8
- let(:tree_id) { 2049 }
9
- let(:path) { '\\192.168.1.1\example' }
9
+ let(:tree_id) { 2050 }
10
+ let(:path) { "\\\\#{ip}\\example" }
10
11
  let(:response) {
11
12
  packet = RubySMB::SMB1::Packet::TreeConnectResponse.new
12
13
  packet.smb_header.tid = tree_id
13
14
  packet.parameter_block.access_rights.read("\xff\x01\x1f\x00")
14
- packet.data_block.service = 'A:'
15
+ packet.parameter_block.guest_access_rights.read("\xff\x01\x1f\x01")
15
16
  packet
16
17
  }
18
+
19
+ let(:disco_req) { RubySMB::SMB1::Packet::TreeDisconnectRequest.new }
20
+ let(:disco_resp) { RubySMB::SMB1::Packet::TreeDisconnectResponse.new }
21
+
17
22
  subject(:tree) {
18
- described_class.new(client:client, share:path, response:response )
23
+ described_class.new(client: client, share: path, response: response)
19
24
  }
20
25
 
21
26
  it { is_expected.to respond_to :client }
@@ -28,6 +33,10 @@ RSpec.describe RubySMB::SMB1::Tree do
28
33
  expect(tree.client).to eq client
29
34
  end
30
35
 
36
+ it 'inherits the guest permissions from the response packet' do
37
+ expect(tree.guest_permissions).to eq response.parameter_block.guest_access_rights
38
+ end
39
+
31
40
  it 'inherits the permissions from the response packet' do
32
41
  expect(tree.permissions).to eq response.parameter_block.access_rights
33
42
  end
@@ -37,8 +46,12 @@ RSpec.describe RubySMB::SMB1::Tree do
37
46
  end
38
47
 
39
48
  describe '#disconnect!' do
40
- let(:disco_req) { RubySMB::SMB1::Packet::TreeDisconnectRequest.new }
41
- let(:disco_resp) { RubySMB::SMB1::Packet::TreeDisconnectResponse.new }
49
+ it 'calls #set_header_fields' do
50
+ allow(RubySMB::SMB1::Packet::TreeDisconnectRequest).to receive(:new).and_return(disco_req)
51
+ allow(client).to receive(:send_recv).and_return(disco_resp.to_binary_s)
52
+ expect(tree).to receive(:set_header_fields).with(disco_req)
53
+ tree.disconnect!
54
+ end
42
55
 
43
56
  it 'sends a TreeDisconnectRequest with the Tree ID in the header' do
44
57
  allow(RubySMB::SMB1::Packet::TreeDisconnectRequest).to receive(:new).and_return(disco_req)
@@ -53,4 +66,393 @@ RSpec.describe RubySMB::SMB1::Tree do
53
66
  expect(tree.disconnect!).to eq disco_resp.status_code
54
67
  end
55
68
  end
69
+
70
+ describe '#open_file' do
71
+ let(:nt_create_andx_req) { RubySMB::SMB1::Packet::NtCreateAndxRequest.new }
72
+ let(:nt_create_andx_response) { RubySMB::SMB1::Packet::NtCreateAndxResponse.new }
73
+ let(:filename) { "test_file\x00" }
74
+
75
+ before :each do
76
+ allow(RubySMB::SMB1::Packet::NtCreateAndxRequest).to receive(:new).and_return(nt_create_andx_req)
77
+ allow(RubySMB::SMB1::Packet::NtCreateAndxResponse).to receive(:read).and_return(nt_create_andx_response)
78
+ end
79
+
80
+ it 'calls #set_header_fields' do
81
+ allow(client).to receive(:send_recv).and_return(nt_create_andx_response.to_binary_s)
82
+ expect(tree).to receive(:set_header_fields).with(nt_create_andx_req).and_call_original
83
+ tree.open_file(filename: filename)
84
+ end
85
+
86
+ describe 'filename' do
87
+ it 'takes the filename as an argument' do
88
+ allow(client).to receive(:send_recv) do |packet|
89
+ expect(packet.data_block.file_name).to eq(filename)
90
+ nt_create_andx_response.to_binary_s
91
+ end
92
+ tree.open_file(filename: filename)
93
+ end
94
+
95
+ it 'adds the null termination to the filename if missing' do
96
+ allow(client).to receive(:send_recv) do |packet|
97
+ expect(packet.data_block.file_name).to eq(filename)
98
+ nt_create_andx_response.to_binary_s
99
+ end
100
+ tree.open_file(filename: filename.chop)
101
+ end
102
+
103
+ it 'adds the unicode null termination to the filename if Unicode is enabled' do
104
+ unicode_filename = filename.encode('UTF-16LE')
105
+ nt_create_andx_req.smb_header.flags2.unicode = 1
106
+ allow(client).to receive(:send_recv) do |packet|
107
+ expect(packet.data_block.file_name).to eq(unicode_filename.b)
108
+ nt_create_andx_response.to_binary_s
109
+ end
110
+ tree.open_file(filename: unicode_filename.chop)
111
+ end
112
+ end
113
+
114
+ describe 'flags' do
115
+ it 'has the correct default fields set' do
116
+ allow(client).to receive(:send_recv) do |packet|
117
+ expect(packet.parameter_block.flags.request_extended_response).to eq(1)
118
+ nt_create_andx_response.to_binary_s
119
+ end
120
+ tree.open_file(filename: filename)
121
+ end
122
+
123
+ it 'can take the Flags as an argument' do
124
+ flags = { request_extended_response: 0 }
125
+ allow(client).to receive(:send_recv) do |packet|
126
+ expect(packet.parameter_block.flags.request_extended_response).to eq(0)
127
+ nt_create_andx_response.to_binary_s
128
+ end
129
+ tree.open_file(filename: filename, flags: flags)
130
+ end
131
+ end
132
+
133
+ describe 'options' do
134
+ it 'has the correct default fields set' do
135
+ allow(client).to receive(:send_recv) do |packet|
136
+ expect(packet.parameter_block.create_options.directory_file).to eq(0)
137
+ expect(packet.parameter_block.create_options.non_directory_file).to eq(1)
138
+ nt_create_andx_response.to_binary_s
139
+ end
140
+ tree.open_file(filename: filename)
141
+ end
142
+
143
+ it 'can take the Flags as an argument' do
144
+ options = RubySMB::SMB1::BitField::CreateOptions.new(directory_file: 1)
145
+ allow(client).to receive(:send_recv) do |packet|
146
+ expect(packet.parameter_block.create_options.directory_file).to eq(1)
147
+ expect(packet.parameter_block.create_options.non_directory_file).to eq(0)
148
+ nt_create_andx_response.to_binary_s
149
+ end
150
+ tree.open_file(filename: filename, options: options)
151
+ end
152
+ end
153
+
154
+ describe 'disposition' do
155
+ it 'defaults to FILE_OPEN' do
156
+ allow(client).to receive(:send_recv) do |packet|
157
+ expect(packet.parameter_block.create_disposition).to eq(RubySMB::Dispositions::FILE_OPEN)
158
+ nt_create_andx_response.to_binary_s
159
+ end
160
+ tree.open_file(filename: filename)
161
+ end
162
+
163
+ it 'can take the Disposition as an argument' do
164
+ allow(client).to receive(:send_recv) do |packet|
165
+ expect(packet.parameter_block.create_disposition).to eq(RubySMB::Dispositions::FILE_OPEN_IF)
166
+ nt_create_andx_response.to_binary_s
167
+ end
168
+ tree.open_file(filename: filename, disposition: RubySMB::Dispositions::FILE_OPEN_IF)
169
+ end
170
+ end
171
+
172
+ describe 'impersonation level' do
173
+ it 'defaults to SEC_IMPERSONATE' do
174
+ allow(client).to receive(:send_recv) do |packet|
175
+ expect(packet.parameter_block.impersonation_level).to eq(RubySMB::ImpersonationLevels::SEC_IMPERSONATE)
176
+ nt_create_andx_response.to_binary_s
177
+ end
178
+ tree.open_file(filename: filename)
179
+ end
180
+
181
+ it 'can take the Impersonation Level as an argument' do
182
+ allow(client).to receive(:send_recv) do |packet|
183
+ expect(packet.parameter_block.impersonation_level).to eq(RubySMB::ImpersonationLevels::SEC_DELEGATE)
184
+ nt_create_andx_response.to_binary_s
185
+ end
186
+ tree.open_file(filename: filename, impersonation: RubySMB::ImpersonationLevels::SEC_DELEGATE)
187
+ end
188
+ end
189
+
190
+ describe 'RWD access permissions' do
191
+ it 'will set the read permission from the parameters' do
192
+ allow(client).to receive(:send_recv) do |packet|
193
+ expect(packet.parameter_block.share_access.share_read).to eq(1)
194
+ expect(packet.parameter_block.desired_access.read_data).to eq(1)
195
+ expect(packet.parameter_block.desired_access.read_ea).to eq(1)
196
+ expect(packet.parameter_block.desired_access.read_attr).to eq(1)
197
+ expect(packet.parameter_block.desired_access.read_control).to eq(1)
198
+ nt_create_andx_response.to_binary_s
199
+ end
200
+ tree.open_file(filename: filename, read: true)
201
+ end
202
+
203
+ it 'will set the write permission from the parameters' do
204
+ allow(client).to receive(:send_recv) do |packet|
205
+ expect(packet.parameter_block.share_access.share_write).to eq(1)
206
+ expect(packet.parameter_block.desired_access.write_data).to eq(1)
207
+ expect(packet.parameter_block.desired_access.append_data).to eq(1)
208
+ expect(packet.parameter_block.desired_access.write_ea).to eq(1)
209
+ expect(packet.parameter_block.desired_access.write_attr).to eq(1)
210
+ nt_create_andx_response.to_binary_s
211
+ end
212
+ tree.open_file(filename: filename, write: true)
213
+ end
214
+
215
+ it 'will set the delete permission from the parameters' do
216
+ allow(client).to receive(:send_recv) do |packet|
217
+ expect(packet.parameter_block.share_access.share_delete).to eq(1)
218
+ expect(packet.parameter_block.desired_access.delete_access).to eq(1)
219
+ nt_create_andx_response.to_binary_s
220
+ end
221
+ tree.open_file(filename: filename, delete: true)
222
+ end
223
+ end
224
+
225
+ it 'sends the NtCreateAndxRequest request packet and gets the expected NtCreateAndxResponse response back' do
226
+ expect(client).to receive(:send_recv).with(nt_create_andx_req).and_return(nt_create_andx_response.to_binary_s)
227
+ tree.open_file(filename: filename)
228
+ end
229
+
230
+ context 'when sending the request packet and gets a response back' do
231
+ before :example do
232
+ allow(client).to receive(:send_recv).with(nt_create_andx_req).and_return(nt_create_andx_response.to_binary_s)
233
+ end
234
+
235
+ it 'returns the expected RubySMB::SMB1::File object' do
236
+ file_obj = RubySMB::SMB1::File.new(name: filename, tree: tree, response: nt_create_andx_response)
237
+ expect(RubySMB::SMB1::File).to receive(:new).with(name: filename, tree: tree, response: nt_create_andx_response).and_return(file_obj)
238
+ expect(tree.open_file(filename: filename)).to eq(file_obj)
239
+ end
240
+
241
+ context 'when the response is not a NtCreateAndxResponse packet' do
242
+ it 'raise an InvalidPacket exception' do
243
+ nt_create_andx_response.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_ECHO
244
+ expect { tree.open_file(filename: filename) }.to raise_error(RubySMB::Error::InvalidPacket)
245
+ end
246
+ end
247
+
248
+ context 'when the response status code is not STATUS_SUCCESS' do
249
+ it 'raise an UnexpectedStatusCode exception' do
250
+ nt_create_andx_response.smb_header.nt_status = WindowsError::NTStatus::STATUS_INVALID_HANDLE.value
251
+ expect { tree.open_file(filename: filename) }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
252
+ end
253
+ end
254
+ end
255
+ end
256
+
257
+ describe '#list' do
258
+ let(:find_first2_req) { RubySMB::SMB1::Packet::Trans2::FindFirst2Request.new }
259
+ let(:file_info1) do
260
+ file_info = RubySMB::SMB1::Packet::Trans2::FindInformationLevel::FindFileFullDirectoryInfo.new
261
+ file_info.unicode = true
262
+ file_info.file_name = 'test1.txt'
263
+ file_info
264
+ end
265
+ let(:find_first2_res) do
266
+ packet = RubySMB::SMB1::Packet::Trans2::FindFirst2Response.new
267
+ packet.data_block.trans2_parameters.eos = 1
268
+ packet.data_block.trans2_data.buffer = file_info1.to_binary_s
269
+ packet
270
+ end
271
+
272
+ before :each do
273
+ allow(RubySMB::SMB1::Packet::Trans2::FindFirst2Request).to receive(:new).and_return(find_first2_req)
274
+ allow(client).to receive(:send_recv)
275
+ allow(RubySMB::SMB1::Packet::Trans2::FindFirst2Response).to receive(:read).and_return(find_first2_res)
276
+ end
277
+
278
+ it 'calls #set_header_fields' do
279
+ expect(tree).to receive(:set_header_fields).with(find_first2_req).and_call_original
280
+ tree.list
281
+ end
282
+
283
+ it 'sets the unicode flag when the unicode argument is true (default)' do
284
+ allow(client).to receive(:send_recv).with(find_first2_req) do |packet|
285
+ expect(packet.smb_header.flags2.unicode).to eq 1
286
+ end
287
+ tree.list
288
+ end
289
+
290
+ it 'does not set the unicode flag when the unicode argument is false' do
291
+ allow(client).to receive(:send_recv).with(find_first2_req) do |packet|
292
+ expect(packet.smb_header.flags2.unicode).to eq 0
293
+ end
294
+ tree.list(unicode: false)
295
+ end
296
+
297
+ it 'adds a leading and trailing \\ to the search path if not present' do
298
+ directory = 'dir'
299
+ search = ('\\' + directory + '\\*').encode('UTF-16LE')
300
+ allow(client).to receive(:send_recv).with(find_first2_req) do |packet|
301
+ expect(packet.data_block.trans2_parameters.filename).to eq search
302
+ end
303
+ tree.list(directory: directory)
304
+ end
305
+
306
+ it 'sets the expected default search parameters' do
307
+ allow(client).to receive(:send_recv).with(find_first2_req) do |packet|
308
+ t2_params = packet.data_block.trans2_parameters
309
+ expect(t2_params.search_attributes.hidden).to eq 1
310
+ expect(t2_params.search_attributes.system).to eq 1
311
+ expect(t2_params.search_attributes.directory).to eq 1
312
+ expect(t2_params.flags.close_eos).to eq 1
313
+ expect(t2_params.flags.resume_keys).to eq 0
314
+ expect(t2_params.information_level).to eq RubySMB::SMB1::Packet::Trans2::FindInformationLevel::FindFileFullDirectoryInfo::CLASS_LEVEL
315
+ expect(t2_params.filename).to eq '\\*'.encode('UTF-16LE')
316
+ expect(t2_params.search_count).to eq 10
317
+ end
318
+ tree.list
319
+ end
320
+
321
+ it 'calls #set_find_params' do
322
+ expect(tree).to receive(:set_find_params).with(find_first2_req).and_call_original
323
+ tree.list
324
+ end
325
+
326
+ it 'calls FindFileFullDirectoryInfo#results' do
327
+ expect(find_first2_res).to receive(:results).with(RubySMB::SMB1::Packet::Trans2::FindInformationLevel::FindFileFullDirectoryInfo, unicode: true).and_call_original
328
+ tree.list
329
+ end
330
+
331
+ it 'returns the expected FindFileFullDirectoryInfo structure' do
332
+ expect(tree.list).to eq([file_info1])
333
+ end
334
+
335
+ it 'returns the expected FindFileFullDirectoryInfo structures when multiple files are listed' do
336
+ file_info1.next_offset = file_info1.do_num_bytes
337
+ file_info2 = RubySMB::SMB1::Packet::Trans2::FindInformationLevel::FindFileFullDirectoryInfo.new
338
+ file_info2.unicode = true
339
+ file_info2.file_name = 'test2.txt'
340
+ find_first2_res.data_block.trans2_data.buffer = file_info1.to_binary_s + file_info2.to_binary_s
341
+
342
+ expect(tree.list).to eq([file_info1, file_info2])
343
+ end
344
+
345
+ context 'when more requests are needed to get all the information' do
346
+ let(:find_next2_req) { RubySMB::SMB1::Packet::Trans2::FindNext2Request.new }
347
+ let(:file_info2) do
348
+ file_info = RubySMB::SMB1::Packet::Trans2::FindInformationLevel::FindFileFullDirectoryInfo.new
349
+ file_info.unicode = true
350
+ file_info.file_name = 'test2.txt'
351
+ file_info
352
+ end
353
+ let(:find_next2_res) do
354
+ packet = RubySMB::SMB1::Packet::Trans2::FindNext2Response.new
355
+ packet.data_block.trans2_parameters.eos = 1
356
+ packet.data_block.trans2_data.buffer = file_info2.to_binary_s
357
+ packet
358
+ end
359
+ let(:sid) { 0x1000 }
360
+
361
+ before :each do
362
+ find_first2_res.data_block.trans2_parameters.eos = 0
363
+ find_first2_res.data_block.trans2_parameters.sid = sid
364
+ allow(RubySMB::SMB1::Packet::Trans2::FindNext2Request).to receive(:new).and_return(find_next2_req)
365
+ allow(client).to receive(:send_recv).with(find_next2_req)
366
+ allow(RubySMB::SMB1::Packet::Trans2::FindNext2Response).to receive(:read).and_return(find_next2_res)
367
+ end
368
+
369
+ it 'calls #set_header_fields' do
370
+ expect(tree).to receive(:set_header_fields).with(find_first2_req).once.ordered.and_call_original
371
+ expect(tree).to receive(:set_header_fields).with(find_next2_req).once.ordered.and_call_original
372
+ tree.list
373
+ end
374
+
375
+ it 'sets the unicode flag when the unicode argument is true (default)' do
376
+ allow(client).to receive(:send_recv).with(find_next2_req) do |packet|
377
+ expect(packet.smb_header.flags2.unicode).to eq 1
378
+ end
379
+ tree.list
380
+ end
381
+
382
+ it 'does not set the unicode flag when the unicode argument is false' do
383
+ allow(client).to receive(:send_recv).with(find_next2_req) do |packet|
384
+ expect(packet.smb_header.flags2.unicode).to eq 0
385
+ end
386
+ tree.list(unicode: false)
387
+ end
388
+
389
+ it 'sets the expected default search parameters' do
390
+ allow(client).to receive(:send_recv).with(find_next2_req) do |packet|
391
+ t2_params = packet.data_block.trans2_parameters
392
+ expect(t2_params.sid).to eq sid
393
+ expect(t2_params.flags.close_eos).to eq 1
394
+ expect(t2_params.flags.resume_keys).to eq 0
395
+ expect(t2_params.information_level).to eq RubySMB::SMB1::Packet::Trans2::FindInformationLevel::FindFileFullDirectoryInfo::CLASS_LEVEL
396
+ expect(t2_params.filename).to eq file_info1.file_name
397
+ expect(t2_params.search_count).to eq 10
398
+ end
399
+ tree.list
400
+ end
401
+
402
+ it 'calls #set_find_params' do
403
+ expect(tree).to receive(:set_find_params).with(find_first2_req).once.ordered.and_call_original
404
+ expect(tree).to receive(:set_find_params).with(find_next2_req).once.ordered.and_call_original
405
+ tree.list
406
+ end
407
+
408
+ it 'calls FindFileFullDirectoryInfo#results' do
409
+ expect(find_first2_res).to receive(:results).with(RubySMB::SMB1::Packet::Trans2::FindInformationLevel::FindFileFullDirectoryInfo, unicode: true).once.ordered.and_call_original
410
+ expect(find_next2_res).to receive(:results).with(RubySMB::SMB1::Packet::Trans2::FindInformationLevel::FindFileFullDirectoryInfo, unicode: true).once.ordered.and_call_original
411
+ tree.list
412
+ end
413
+
414
+ it 'returns the expected FindFileFullDirectoryInfo structures' do
415
+ expect(tree.list).to eq([file_info1, file_info2])
416
+ end
417
+ end
418
+ end
419
+
420
+ describe '#set_header_fields' do
421
+ let(:modified_request) { tree.set_header_fields(disco_req) }
422
+ it 'adds the TreeID to the header' do
423
+ expect(modified_request.smb_header.tid).to eq tree.id
424
+ end
425
+
426
+ it 'sets the Flags2 extended attributes field to 1' do
427
+ expect(modified_request.smb_header.flags2.eas).to eq 1
428
+ end
429
+ end
430
+
431
+ describe '#set_find_params' do
432
+ let(:find_first2_req) { RubySMB::SMB1::Packet::Trans2::FindFirst2Request.new }
433
+ let(:modified_request) { tree.send(:set_find_params, find_first2_req) }
434
+
435
+ it 'sets #data_count to 0' do
436
+ expect(modified_request.parameter_block.data_count).to eq 0
437
+ end
438
+
439
+ it 'sets #data_offset to 0' do
440
+ expect(modified_request.parameter_block.data_offset).to eq 0
441
+ end
442
+
443
+ it 'sets #total_parameter_count to #parameter_count value' do
444
+ find_first2_req.parameter_block.parameter_count = 10
445
+ expect(modified_request.parameter_block.total_parameter_count).to eq 10
446
+ end
447
+
448
+ it 'sets #max_parameter_count to #parameter_count value' do
449
+ find_first2_req.parameter_block.parameter_count = 10
450
+ expect(modified_request.parameter_block.max_parameter_count).to eq 10
451
+ end
452
+
453
+ it 'sets #max_data_count to 16,384' do
454
+ expect(modified_request.parameter_block.max_data_count).to eq 16_384
455
+ end
456
+ end
457
+
56
458
  end