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
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RubySMB::SMB2::Packet::SessionSetupResponse do
4
-
5
4
  subject(:packet) { described_class.new }
6
5
 
7
6
  it { is_expected.to respond_to :smb2_header }
@@ -32,7 +31,7 @@ RSpec.describe RubySMB::SMB2::Packet::SessionSetupResponse do
32
31
  end
33
32
 
34
33
  describe '#set_type2_blob' do
35
- let(:fake_message) { "foo" }
34
+ let(:fake_message) { 'foo' }
36
35
 
37
36
  it 'calls the #gss_type2 method to create a blob' do
38
37
  expect(RubySMB::Gss).to receive(:gss_type2).with(fake_message).and_return(fake_message)
@@ -51,4 +50,4 @@ RSpec.describe RubySMB::SMB2::Packet::SessionSetupResponse do
51
50
  expect(packet.security_buffer_length).to eq fake_message.length
52
51
  end
53
52
  end
54
- end
53
+ end
@@ -0,0 +1,205 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::SMB2::Packet::SetInfoRequest do
4
+ subject(:packet) { described_class.new }
5
+
6
+ it { is_expected.to respond_to :smb2_header }
7
+ it { is_expected.to respond_to :structure_size }
8
+ it { is_expected.to respond_to :info_type }
9
+ it { is_expected.to respond_to :file_info_class }
10
+ it { is_expected.to respond_to :buffer_length }
11
+ it { is_expected.to respond_to :buffer_offset }
12
+ it { is_expected.to respond_to :reserved }
13
+ it { is_expected.to respond_to :additional_information }
14
+ it { is_expected.to respond_to :file_id }
15
+ it { is_expected.to respond_to :buffer }
16
+
17
+ it 'is little endian' do
18
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
19
+ end
20
+
21
+ describe '#smb2_header' do
22
+ subject(:header) { packet.smb2_header }
23
+
24
+ it 'is a standard SMB2 Header' do
25
+ expect(header).to be_a RubySMB::SMB2::SMB2Header
26
+ end
27
+
28
+ it 'should have the command set to SMB_INFO' do
29
+ expect(header.command).to eq RubySMB::SMB2::Commands::SET_INFO
30
+ end
31
+
32
+ it 'should not have the response flag set' do
33
+ expect(header.flags.reply).to eq 0
34
+ end
35
+ end
36
+
37
+ describe '#structure_size' do
38
+ it 'is a 16-bit field' do
39
+ expect(packet.structure_size).to be_a BinData::Uint16le
40
+ end
41
+
42
+ it 'has a default value of 33' do
43
+ expect(packet.structure_size).to eq 33
44
+ end
45
+ end
46
+
47
+ describe '#info_type' do
48
+ it 'is a 8-bit field' do
49
+ expect(packet.info_type).to be_a BinData::Uint8
50
+ end
51
+
52
+ it 'has a default value of SMB2_0_INFO_FILE' do
53
+ expect(packet.info_type).to eq RubySMB::SMB2::InfoType::SMB2_0_INFO_FILE
54
+ end
55
+ end
56
+
57
+ describe '#file_info_class' do
58
+ it 'is a 8-bit field' do
59
+ expect(packet.file_info_class).to be_a BinData::Uint8
60
+ end
61
+ end
62
+
63
+ describe '#buffer_length' do
64
+ it 'is a 32-bit field' do
65
+ expect(packet.buffer_length).to be_a BinData::Uint32le
66
+ end
67
+
68
+ it 'is set to the buffer size' do
69
+ packet.file_info_class = RubySMB::Fscc::FileInformation::FILE_FULL_DIRECTORY_INFORMATION
70
+ expect(packet.buffer_length).to eq packet.buffer.do_num_bytes
71
+ end
72
+ end
73
+
74
+ describe '#buffer_offset' do
75
+ it 'is a 16-bit field' do
76
+ expect(packet.buffer_offset).to be_a BinData::Uint16le
77
+ end
78
+
79
+ it 'is set to the buffer size' do
80
+ packet.file_info_class = RubySMB::Fscc::FileInformation::FILE_FULL_DIRECTORY_INFORMATION
81
+ expect(packet.buffer_offset).to eq packet.buffer.abs_offset
82
+ end
83
+ end
84
+
85
+ describe '#additional_information' do
86
+ subject(:additional_information) { packet.additional_information }
87
+
88
+ it { is_expected.to respond_to :scope_security_information }
89
+ it { is_expected.to respond_to :attribute_security_information }
90
+ it { is_expected.to respond_to :label_security_information }
91
+ it { is_expected.to respond_to :sacl_security_information }
92
+ it { is_expected.to respond_to :dacl_security_information }
93
+ it { is_expected.to respond_to :group_security_information }
94
+ it { is_expected.to respond_to :owner_security_information }
95
+ it { is_expected.to respond_to :backup_security_information }
96
+
97
+ describe '#scope_security_information' do
98
+ it 'should be a 1-bit field per the SMB spec' do
99
+ expect(additional_information.scope_security_information).to be_a BinData::Bit1
100
+ end
101
+
102
+ it_behaves_like 'bit field with one flag set', :scope_security_information, 'V', 0x00000040
103
+ end
104
+
105
+ describe '#attribute_security_information' do
106
+ it 'should be a 1-bit field per the SMB spec' do
107
+ expect(additional_information.attribute_security_information).to be_a BinData::Bit1
108
+ end
109
+
110
+ it_behaves_like 'bit field with one flag set', :attribute_security_information, 'V', 0x00000020
111
+ end
112
+
113
+ describe '#label_security_information' do
114
+ it 'should be a 1-bit field per the SMB spec' do
115
+ expect(additional_information.label_security_information).to be_a BinData::Bit1
116
+ end
117
+
118
+ it_behaves_like 'bit field with one flag set', :label_security_information, 'V', 0x00000010
119
+ end
120
+
121
+ describe '#sacl_security_information' do
122
+ it 'should be a 1-bit field per the SMB spec' do
123
+ expect(additional_information.sacl_security_information).to be_a BinData::Bit1
124
+ end
125
+
126
+ it_behaves_like 'bit field with one flag set', :sacl_security_information, 'V', 0x00000008
127
+ end
128
+
129
+ describe '#dacl_security_information' do
130
+ it 'should be a 1-bit field per the SMB spec' do
131
+ expect(additional_information.dacl_security_information).to be_a BinData::Bit1
132
+ end
133
+
134
+ it_behaves_like 'bit field with one flag set', :dacl_security_information, 'V', 0x00000004
135
+ end
136
+
137
+ describe '#group_security_information' do
138
+ it 'should be a 1-bit field per the SMB spec' do
139
+ expect(additional_information.group_security_information).to be_a BinData::Bit1
140
+ end
141
+
142
+ it_behaves_like 'bit field with one flag set', :group_security_information, 'V', 0x00000002
143
+ end
144
+
145
+ describe '#owner_security_information' do
146
+ it 'should be a 1-bit field per the SMB spec' do
147
+ expect(additional_information.owner_security_information).to be_a BinData::Bit1
148
+ end
149
+
150
+ it_behaves_like 'bit field with one flag set', :owner_security_information, 'V', 0x00000001
151
+ end
152
+
153
+ describe '#backup_security_information' do
154
+ it 'should be a 1-bit field per the SMB spec' do
155
+ expect(additional_information.backup_security_information).to be_a BinData::Bit1
156
+ end
157
+
158
+ it_behaves_like 'bit field with one flag set', :backup_security_information, 'V', 0x00010000
159
+ end
160
+ end
161
+
162
+ describe '#file_id' do
163
+ it 'is a Smb2Fileid field' do
164
+ expect(packet.file_id).to be_a RubySMB::Field::Smb2Fileid
165
+ end
166
+ end
167
+
168
+ describe '#buffer' do
169
+ context 'when file_info_class is set' do
170
+ it 'is set to a FileDirectoryInformation class with the FILE_DIRECTORY_INFORMATION code' do
171
+ packet.file_info_class = RubySMB::Fscc::FileInformation::FILE_DIRECTORY_INFORMATION
172
+ expect(packet.buffer).to eq RubySMB::Fscc::FileInformation::FileDirectoryInformation.new
173
+ end
174
+ it 'is set to a FileFullDirectoryInformation class with the FILE_FULL_DIRECTORY_INFORMATION code' do
175
+ packet.file_info_class = RubySMB::Fscc::FileInformation::FILE_FULL_DIRECTORY_INFORMATION
176
+ expect(packet.buffer).to eq RubySMB::Fscc::FileInformation::FileFullDirectoryInformation.new
177
+ end
178
+ it 'is set to a FileDispositionInformation class with the FILE_DISPOSITION_INFORMATION code' do
179
+ packet.file_info_class = RubySMB::Fscc::FileInformation::FILE_DISPOSITION_INFORMATION
180
+ expect(packet.buffer).to eq RubySMB::Fscc::FileInformation::FileDispositionInformation.new
181
+ end
182
+ it 'is set to a FileIdFullDirectoryInformation class with the FILE_ID_FULL_DIRECTORY_INFORMATION code' do
183
+ packet.file_info_class = RubySMB::Fscc::FileInformation::FILE_ID_FULL_DIRECTORY_INFORMATION
184
+ expect(packet.buffer).to eq RubySMB::Fscc::FileInformation::FileIdFullDirectoryInformation.new
185
+ end
186
+ it 'is set to a FileBothDirectoryInformation class with the FILE_BOTH_DIRECTORY_INFORMATION code' do
187
+ packet.file_info_class = RubySMB::Fscc::FileInformation::FILE_BOTH_DIRECTORY_INFORMATION
188
+ expect(packet.buffer).to eq RubySMB::Fscc::FileInformation::FileBothDirectoryInformation.new
189
+ end
190
+ it 'is set to a FileIdBothDirectoryInformation class with the FILE_ID_BOTH_DIRECTORY_INFORMATION code' do
191
+ packet.file_info_class = RubySMB::Fscc::FileInformation::FILE_ID_BOTH_DIRECTORY_INFORMATION
192
+ expect(packet.buffer).to eq RubySMB::Fscc::FileInformation::FileIdBothDirectoryInformation.new
193
+ end
194
+ it 'is set to a FileNamesInformation class with the FILE_NAMES_INFORMATION code' do
195
+ packet.file_info_class = RubySMB::Fscc::FileInformation::FILE_NAMES_INFORMATION
196
+ expect(packet.buffer).to eq RubySMB::Fscc::FileInformation::FileNamesInformation.new
197
+ end
198
+ it 'is set to a FileRenameInformation class with the FILE_RENAME_INFORMATION code' do
199
+ packet.file_info_class = RubySMB::Fscc::FileInformation::FILE_RENAME_INFORMATION
200
+ expect(packet.buffer).to eq RubySMB::Fscc::FileInformation::FileRenameInformation.new
201
+ end
202
+ end
203
+ end
204
+
205
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::SMB2::Packet::SetInfoResponse do
4
+ subject(:packet) { described_class.new }
5
+
6
+ it { is_expected.to respond_to :smb2_header }
7
+ it { is_expected.to respond_to :structure_size }
8
+
9
+ it 'is little endian' do
10
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
11
+ end
12
+
13
+ describe '#smb2_header' do
14
+ subject(:header) { packet.smb2_header }
15
+
16
+ it 'is a standard SMB Header' do
17
+ expect(header).to be_a RubySMB::SMB2::SMB2Header
18
+ end
19
+
20
+ it 'should have the command set to SMB_COM_NEGOTIATE' do
21
+ expect(header.command).to eq RubySMB::SMB2::Commands::SET_INFO
22
+ end
23
+
24
+ it 'should have the response flag set' do
25
+ expect(header.flags.reply).to eq 1
26
+ end
27
+ end
28
+
29
+ it 'should have a structure size of 17' do
30
+ expect(packet.structure_size).to eq 2
31
+ end
32
+ end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RubySMB::SMB2::Packet::TreeConnectRequest do
4
-
5
4
  subject(:packet) { described_class.new }
6
5
 
7
6
  it { is_expected.to respond_to :smb2_header }
@@ -11,7 +10,6 @@ RSpec.describe RubySMB::SMB2::Packet::TreeConnectRequest do
11
10
  it { is_expected.to respond_to :path_length }
12
11
  it { is_expected.to respond_to :path }
13
12
 
14
-
15
13
  it 'is little endian' do
16
14
  expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
17
15
  end
@@ -33,8 +31,8 @@ RSpec.describe RubySMB::SMB2::Packet::TreeConnectRequest do
33
31
  end
34
32
 
35
33
  describe '#encode_path' do
36
- let(:path) { "\\192.168.1.1\\example" }
37
- let(:encoded_path) { path.encode("utf-16le").force_encoding("binary") }
34
+ let(:path) { '\\192.168.1.1\\example' }
35
+ let(:encoded_path) { path.encode('utf-16le').force_encoding('binary') }
38
36
 
39
37
  it 'sets the path string to a UTF-16LE version of the supplied string' do
40
38
  packet.encode_path(path)
@@ -46,4 +44,4 @@ RSpec.describe RubySMB::SMB2::Packet::TreeConnectRequest do
46
44
  expect(packet.path_length).to eq encoded_path.length
47
45
  end
48
46
  end
49
- end
47
+ end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RubySMB::SMB2::Packet::TreeConnectResponse do
4
-
5
4
  subject(:packet) { described_class.new }
6
5
 
7
6
  it { is_expected.to respond_to :smb2_header }
@@ -54,4 +53,4 @@ RSpec.describe RubySMB::SMB2::Packet::TreeConnectResponse do
54
53
  expect(packet.access_rights).to be_a RubySMB::SMB2::BitField::FileAccessMask
55
54
  end
56
55
  end
57
- end
56
+ end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RubySMB::SMB2::Packet::TreeDisconnectRequest do
4
-
5
4
  subject(:packet) { described_class.new }
6
5
 
7
6
  it { is_expected.to respond_to :smb2_header }
@@ -26,5 +25,4 @@ RSpec.describe RubySMB::SMB2::Packet::TreeDisconnectRequest do
26
25
  expect(header.flags.reply).to eq 0
27
26
  end
28
27
  end
29
-
30
- end
28
+ end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RubySMB::SMB2::Packet::TreeDisconnectResponse do
4
-
5
4
  subject(:packet) { described_class.new }
6
5
 
7
6
  it { is_expected.to respond_to :smb2_header }
@@ -26,5 +25,4 @@ RSpec.describe RubySMB::SMB2::Packet::TreeDisconnectResponse do
26
25
  expect(header.flags.reply).to eq 1
27
26
  end
28
27
  end
29
-
30
- end
28
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::SMB2::Packet::WriteRequest do
4
+ subject(:packet) { described_class.new }
5
+
6
+ it { is_expected.to respond_to :smb2_header }
7
+ it { is_expected.to respond_to :structure_size }
8
+ it { is_expected.to respond_to :data_offset }
9
+ it { is_expected.to respond_to :flags }
10
+ it { is_expected.to respond_to :write_length }
11
+ it { is_expected.to respond_to :write_offset }
12
+ it { is_expected.to respond_to :file_id }
13
+ it { is_expected.to respond_to :channel }
14
+ it { is_expected.to respond_to :remaining_bytes }
15
+ it { is_expected.to respond_to :channel_offset }
16
+ it { is_expected.to respond_to :channel_length }
17
+ it { is_expected.to respond_to :buffer }
18
+
19
+ it 'is little endian' do
20
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
21
+ end
22
+
23
+ describe '#smb2_header' do
24
+ subject(:header) { packet.smb2_header }
25
+
26
+ it 'is a standard SMB Header' do
27
+ expect(header).to be_a RubySMB::SMB2::SMB2Header
28
+ end
29
+
30
+ it 'should have the command set to SMB_COM_NEGOTIATE' do
31
+ expect(header.command).to eq RubySMB::SMB2::Commands::WRITE
32
+ end
33
+
34
+ it 'should not have the response flag set' do
35
+ expect(header.flags.reply).to eq 0
36
+ end
37
+ end
38
+
39
+ it 'should have a structure size of 49' do
40
+ expect(packet.structure_size).to eq 49
41
+ end
42
+
43
+ it 'stores the offset of the write buffer in #data_offset' do
44
+ expect(packet.data_offset).to eq packet.buffer.abs_offset
45
+ end
46
+
47
+ it 'stores the length of the write buffer in #write_length' do
48
+ packet.buffer = 'hello'
49
+ expect(packet.write_length).to eq packet.buffer.length
50
+ end
51
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::SMB2::Packet::WriteResponse do
4
+ subject(:packet) { described_class.new }
5
+
6
+ it { is_expected.to respond_to :smb2_header }
7
+ it { is_expected.to respond_to :structure_size }
8
+ it { is_expected.to respond_to :write_count }
9
+ it { is_expected.to respond_to :remaining_bytes }
10
+ it { is_expected.to respond_to :channel_offset }
11
+ it { is_expected.to respond_to :channel_length }
12
+
13
+
14
+ it 'is little endian' do
15
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
16
+ end
17
+
18
+ describe '#smb2_header' do
19
+ subject(:header) { packet.smb2_header }
20
+
21
+ it 'is a standard SMB Header' do
22
+ expect(header).to be_a RubySMB::SMB2::SMB2Header
23
+ end
24
+
25
+ it 'should have the command set to SMB_COM_NEGOTIATE' do
26
+ expect(header.command).to eq RubySMB::SMB2::Commands::WRITE
27
+ end
28
+
29
+ it 'should have the response flag set' do
30
+ expect(header.flags.reply).to eq 1
31
+ end
32
+ end
33
+
34
+ it 'should have a structure size of 49' do
35
+ expect(packet.structure_size).to eq 17
36
+ end
37
+
38
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe RubySMB::SMB2::Tree do
4
- let(:sock) { double("Socket", peeraddr: '192.168.1.5' ) }
4
+ let(:sock) { double('Socket', peeraddr: '192.168.1.5') }
5
5
  let(:dispatcher) { RubySMB::Dispatcher::Socket.new(sock) }
6
6
 
7
7
  let(:client) { RubySMB::Client.new(dispatcher, username: 'msfadmin', password: 'msfadmin') }
@@ -14,8 +14,12 @@ RSpec.describe RubySMB::SMB2::Tree do
14
14
  packet.share_type = 0x01
15
15
  packet
16
16
  }
17
+
18
+ let(:disco_req) { RubySMB::SMB2::Packet::TreeDisconnectRequest.new }
19
+ let(:disco_resp) { RubySMB::SMB2::Packet::TreeDisconnectResponse.new }
20
+
17
21
  subject(:tree) {
18
- described_class.new(client:client, share:path, response:response )
22
+ described_class.new(client: client, share: path, response: response)
19
23
  }
20
24
 
21
25
  it { is_expected.to respond_to :client }
@@ -36,9 +40,6 @@ RSpec.describe RubySMB::SMB2::Tree do
36
40
  end
37
41
 
38
42
  describe '#disconnect!' do
39
- let(:disco_req) { RubySMB::SMB2::Packet::TreeDisconnectRequest.new }
40
- let(:disco_resp) { RubySMB::SMB2::Packet::TreeDisconnectResponse.new }
41
-
42
43
  it 'sends a TreeDisconnectRequest with the Tree ID in the header' do
43
44
  allow(RubySMB::SMB2::Packet::TreeDisconnectRequest).to receive(:new).and_return(disco_req)
44
45
  modified_req = disco_req
@@ -52,4 +53,189 @@ RSpec.describe RubySMB::SMB2::Tree do
52
53
  expect(tree.disconnect!).to eq disco_resp.status_code
53
54
  end
54
55
  end
56
+
57
+ describe '#set_header_fields' do
58
+ let(:modified_request) { tree.set_header_fields(disco_req) }
59
+ it 'adds the TreeID to the header' do
60
+ expect(modified_request.smb2_header.tree_id).to eq tree.id
61
+ end
62
+
63
+ it 'sets the credit charge to 1' do
64
+ expect(modified_request.smb2_header.credit_charge).to eq 1
65
+ end
66
+
67
+ it 'sets the credits to 256' do
68
+ expect(modified_request.smb2_header.credits).to eq 256
69
+ end
70
+ end
71
+
72
+ describe '#open_directory_packet' do
73
+ describe 'directory name' do
74
+ it 'uses a null byte of nothing is passed in' do
75
+ expect(tree.open_directory_packet.name).to eq "\x00".encode('UTF-16LE')
76
+ end
77
+
78
+ it 'sets the #name_length to 0 if no name is passed in' do
79
+ expect(tree.open_directory_packet.name_length).to eq 0
80
+ end
81
+
82
+ it 'encodes any supplied file name in UTF-16LE' do
83
+ name = 'hello.txt'
84
+ expect(tree.open_directory_packet(directory: name).name).to eq name.encode('UTF-16LE')
85
+ end
86
+ end
87
+
88
+ describe 'disposition' do
89
+ it 'defaults to FILE_OPEN' do
90
+ expect(tree.open_directory_packet.create_disposition).to eq RubySMB::Dispositions::FILE_OPEN
91
+ end
92
+
93
+ it 'can take the Disposition as an argument' do
94
+ expect(tree.open_directory_packet(disposition: RubySMB::Dispositions::FILE_OPEN_IF).create_disposition).to eq RubySMB::Dispositions::FILE_OPEN_IF
95
+ end
96
+ end
97
+
98
+ describe 'impersonation level' do
99
+ it 'defaults to SEC_IMPERSONATE' do
100
+ expect(tree.open_directory_packet.impersonation_level).to eq RubySMB::ImpersonationLevels::SEC_IMPERSONATE
101
+ end
102
+
103
+ it 'can take the Impersonation Level as an argument' do
104
+ expect(tree.open_directory_packet(impersonation: RubySMB::ImpersonationLevels::SEC_DELEGATE).impersonation_level).to eq RubySMB::ImpersonationLevels::SEC_DELEGATE
105
+ end
106
+ end
107
+
108
+ describe 'RWD access permissions' do
109
+ it 'will set the read permission from the parameters' do
110
+ expect(tree.open_directory_packet(read: true).share_access.read_access).to eq 1
111
+ end
112
+
113
+ it 'will set the write permission from the parameters' do
114
+ expect(tree.open_directory_packet(write: true).share_access.write_access).to eq 1
115
+ end
116
+
117
+ it 'will set the delete permission from the parameters' do
118
+ expect(tree.open_directory_packet(delete: true).share_access.delete_access).to eq 1
119
+ end
120
+ end
121
+ end
122
+
123
+ describe '#open_directory' do
124
+ let(:create_req) { RubySMB::SMB2::Packet::CreateRequest.new }
125
+ let(:create_response) { RubySMB::SMB2::Packet::CreateResponse.new }
126
+
127
+ it 'sends the create request packet and gets a response back' do
128
+ allow(tree).to receive(:open_directory_packet).and_return(create_req)
129
+ expect(client).to receive(:send_recv).with(create_req).and_return(create_response.to_binary_s)
130
+ tree.open_directory
131
+ end
132
+ end
133
+
134
+ describe '#list' do
135
+ let(:create_res) { double('create response') }
136
+ let(:query_dir_req) { RubySMB::SMB2::Packet::QueryDirectoryRequest.new }
137
+ let(:query_dir_res) { RubySMB::SMB2::Packet::QueryDirectoryResponse.new }
138
+
139
+ before :example do
140
+ allow(tree).to receive(:open_directory).and_return(create_res)
141
+ allow(create_res).to receive(:file_id)
142
+ allow(RubySMB::SMB2::Packet::QueryDirectoryRequest).to receive(:new).and_return(query_dir_req)
143
+ allow(client).to receive(:send_recv)
144
+ allow(RubySMB::SMB2::Packet::QueryDirectoryResponse).to receive(:read).and_return(query_dir_res)
145
+ query_dir_res.smb2_header.nt_status = WindowsError::NTStatus::STATUS_NO_MORE_FILES.value
146
+ end
147
+
148
+ it 'calls #open_directory' do
149
+ dir = '/dir'
150
+ expect(tree).to receive(:open_directory).with(directory: dir).and_return(create_res)
151
+ tree.list(directory: dir)
152
+ end
153
+
154
+ it 'uses the File ID from the create response' do
155
+ file_id = RubySMB::Field::Smb2Fileid.new
156
+ allow(create_res).to receive(:file_id).and_return(file_id)
157
+ allow(client).to receive(:send_recv) do |packet|
158
+ expect(packet.file_id).to eq file_id
159
+ end
160
+ tree.list
161
+ end
162
+
163
+ it 'sets the default QueryDirectoryRequest values' do
164
+ allow(client).to receive(:send_recv) do |packet|
165
+ expect(packet.file_information_class).to eq RubySMB::Fscc::FileInformation::FileIdFullDirectoryInformation::CLASS_LEVEL
166
+ expect(packet.name).to eq '*'.encode('UTF-16LE')
167
+ expect(packet.output_length).to eq 65_535
168
+ end
169
+ tree.list
170
+ end
171
+
172
+ it 'sets QueryDirectoryRequest #name field to the pattern passed as argument' do
173
+ pattern = '/dir/*/'.encode('UTF-16LE')
174
+ allow(client).to receive(:send_recv) do |packet|
175
+ expect(packet.name).to eq pattern
176
+ end
177
+ tree.list(pattern: pattern)
178
+ end
179
+
180
+ it 'sets QueryDirectoryRequest #file_information_class field to the type passed as argument' do
181
+ type = RubySMB::Fscc::FileInformation::FileDirectoryInformation
182
+ allow(client).to receive(:send_recv) do |packet|
183
+ expect(packet.file_information_class).to eq type::CLASS_LEVEL
184
+ end
185
+ tree.list(type: type)
186
+ end
187
+
188
+ it 'calls #set_header_fields' do
189
+ expect(tree).to receive(:set_header_fields).with(query_dir_req).and_call_original
190
+ tree.list
191
+ end
192
+
193
+ let(:file1) { double('file information') }
194
+ let(:file2) { double('file information') }
195
+
196
+ it 'returns the expected file information' do
197
+ query_dir_res.smb2_header.nt_status = WindowsError::NTStatus::STATUS_SUCCESS.value
198
+ allow(query_dir_res).to receive(:results) do |_type|
199
+ query_dir_res.smb2_header.nt_status = WindowsError::NTStatus::STATUS_NO_MORE_FILES.value
200
+ [file1]
201
+ end
202
+ expect(tree.list).to eq([file1])
203
+ end
204
+
205
+ context 'when multiple requests are needed to retrieve the full directory list' do
206
+ before :example do
207
+ query_dir_res.smb2_header.nt_status = WindowsError::NTStatus::STATUS_SUCCESS.value
208
+ first_query = true
209
+ allow(query_dir_res).to receive(:results) do |_type|
210
+ if first_query
211
+ first_query = false
212
+ [file1]
213
+ else
214
+ query_dir_res.smb2_header.nt_status = WindowsError::NTStatus::STATUS_NO_MORE_FILES.value
215
+ [file2]
216
+ end
217
+ end
218
+ end
219
+
220
+ it 'returns the expected file information' do
221
+ expect(tree.list).to eq([file1] + [file2])
222
+ end
223
+
224
+ it 'resets the message ID between the requests' do
225
+ allow(client).to receive(:send_recv) do |packet|
226
+ expect(packet.smb2_header.message_id).to eq 0
227
+ packet.smb2_header.message_id = 1
228
+ end
229
+ tree.list
230
+ end
231
+ end
232
+
233
+ context 'when an unexpected status code is received' do
234
+ it 'raises an exception' do
235
+ query_dir_res.smb2_header.nt_status = WindowsError::NTStatus::STATUS_FILE_NOT_AVAILABLE.value
236
+ expect { tree.list }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
237
+ end
238
+ end
239
+
240
+ end
55
241
  end