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
@@ -34,7 +34,6 @@ RSpec.describe RubySMB::SMB2::BitField::DirectoryAccessMask do
34
34
  it_behaves_like 'bit field with one flag set', :list, 'V', 0x00000001
35
35
  end
36
36
 
37
-
38
37
  describe '#add_file' do
39
38
  it 'should be a 1-bit field per the SMB spec' do
40
39
  expect(flags.add_file).to be_a BinData::Bit1
@@ -186,5 +185,4 @@ RSpec.describe RubySMB::SMB2::BitField::DirectoryAccessMask do
186
185
 
187
186
  it_behaves_like 'bit field with one flag set', :generic_read, 'V', 0x80000000
188
187
  end
189
-
190
188
  end
@@ -34,7 +34,6 @@ RSpec.describe RubySMB::SMB2::BitField::FileAccessMask do
34
34
  it_behaves_like 'bit field with one flag set', :read_data, 'V', 0x00000001
35
35
  end
36
36
 
37
-
38
37
  describe '#write_data' do
39
38
  it 'should be a 1-bit field per the SMB spec' do
40
39
  expect(flags.write_data).to be_a BinData::Bit1
@@ -186,5 +185,4 @@ RSpec.describe RubySMB::SMB2::BitField::FileAccessMask do
186
185
 
187
186
  it_behaves_like 'bit field with one flag set', :generic_read, 'V', 0x80000000
188
187
  end
189
-
190
188
  end
@@ -25,4 +25,4 @@ RSpec.describe RubySMB::SMB2::BitField::SessionFlags do
25
25
 
26
26
  it_behaves_like 'bit field with one flag set', :null, 'v', 0x00000002
27
27
  end
28
- end
28
+ end
@@ -7,7 +7,6 @@ RSpec.describe RubySMB::SMB2::BitField::ShareCapabilities do
7
7
  it { is_expected.to respond_to :continuous }
8
8
  it { is_expected.to respond_to :dfs }
9
9
 
10
-
11
10
  it 'is little endian' do
12
11
  expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
13
12
  end
@@ -24,7 +24,6 @@ RSpec.describe RubySMB::SMB2::BitField::ShareFlags do
24
24
  it_behaves_like 'bit field with one flag set', :dfs, 'V', 0x00000001
25
25
  end
26
26
 
27
-
28
27
  describe '#dfs_root' do
29
28
  it 'should be a 1-bit field per the SMB spec' do
30
29
  expect(flags.dfs_root).to be_a BinData::Bit1
@@ -179,6 +178,5 @@ RSpec.describe RubySMB::SMB2::BitField::ShareFlags do
179
178
  flags.vdo_caching = 0
180
179
  expect(flags.caching_type).to eq :manual
181
180
  end
182
-
183
181
  end
184
182
  end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::SMB2::CreateContext do
4
+ subject(:struct) { described_class.new }
5
+
6
+ it { is_expected.to respond_to :next_offset }
7
+ it { is_expected.to respond_to :name_offset }
8
+ it { is_expected.to respond_to :name_length }
9
+ it { is_expected.to respond_to :data_offset }
10
+ it { is_expected.to respond_to :data_length }
11
+ it { is_expected.to respond_to :name }
12
+ it { is_expected.to respond_to :data }
13
+
14
+ describe '#name_length' do
15
+ it 'stores the length of the name field' do
16
+ expect(struct.name_length).to eq struct.name.length
17
+ end
18
+ end
19
+
20
+ describe '#name_offset' do
21
+ it 'stores the relative offset of the name field' do
22
+ expect(struct.name_offset).to eq struct.name.rel_offset
23
+ end
24
+ end
25
+
26
+ describe '#data_length' do
27
+ it 'stores the length of the data field' do
28
+ expect(struct.data_length).to eq struct.data.length
29
+ end
30
+ end
31
+
32
+ describe '#data_offset' do
33
+ it 'stores the relative offset of the data field' do
34
+ struct.data = 'Hello'
35
+ expect(struct.data_offset).to eq struct.data.rel_offset
36
+ end
37
+
38
+ it 'returns 0 if the data field is empty' do
39
+ expect(struct.data_offset).to eq 0
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,233 @@
1
+ require 'spec_helper'
2
+ require 'securerandom'
3
+
4
+ RSpec.describe RubySMB::SMB2::File do
5
+ let(:sock) { double('Socket', peeraddr: '192.168.1.5') }
6
+ let(:dispatcher) { RubySMB::Dispatcher::Socket.new(sock) }
7
+
8
+ let(:client) { RubySMB::Client.new(dispatcher, username: 'msfadmin', password: 'msfadmin') }
9
+ let(:tree_id) { 2049 }
10
+ let(:path) { '\\192.168.1.1\example' }
11
+ let(:connect_response) {
12
+ packet = RubySMB::SMB2::Packet::TreeConnectResponse.new
13
+ packet.smb2_header.tree_id = tree_id
14
+ packet.maximal_access.read("\xff\x01\x1f\x00")
15
+ packet.share_type = 0x01
16
+ packet
17
+ }
18
+
19
+ let(:disco_req) { RubySMB::SMB2::Packet::TreeDisconnectRequest.new }
20
+ let(:disco_resp) { RubySMB::SMB2::Packet::TreeDisconnectResponse.new }
21
+ let(:tree) { RubySMB::SMB2::Tree.new(client: client, share: path, response: connect_response) }
22
+ let(:file_id) { RubySMB::Field::Smb2Fileid.read('\x6d\x01\x00\x00\x00\x00\x00\x00\x\x01\x00\x00\x00\xff\xff\xff\xff') }
23
+ let(:time) { DateTime.now }
24
+ let(:create_response) {
25
+ RubySMB::SMB2::Packet::CreateResponse.new(
26
+ file_id: file_id,
27
+ end_of_file: 108,
28
+ allocation_size: 112,
29
+ last_access: time,
30
+ last_change: time,
31
+ last_write: time
32
+ )
33
+ }
34
+
35
+ subject(:file) { described_class.new(name: 'short.txt', response: create_response, tree: tree) }
36
+
37
+ it { is_expected.to respond_to :attributes }
38
+ it { is_expected.to respond_to :guid }
39
+ it { is_expected.to respond_to :last_access }
40
+ it { is_expected.to respond_to :last_change }
41
+ it { is_expected.to respond_to :last_write }
42
+ it { is_expected.to respond_to :name }
43
+ it { is_expected.to respond_to :size }
44
+ it { is_expected.to respond_to :size_on_disk }
45
+ it { is_expected.to respond_to :tree }
46
+
47
+ it 'pulls the attributes from the response packet' do
48
+ expect(file.attributes).to eq create_response.file_attributes
49
+ end
50
+
51
+ it 'pulls the GUID from the response fileid' do
52
+ expect(file.guid).to eq create_response.file_id
53
+ end
54
+
55
+ it 'pulls the timestamps from the response packet' do
56
+ expect(file.last_access).to eq create_response.last_access.to_datetime
57
+ end
58
+
59
+ it 'pulls the size from the response packet' do
60
+ expect(file.size).to eq create_response.end_of_file
61
+ end
62
+
63
+ it 'pulls the size_on_disk from the response packet' do
64
+ expect(file.size_on_disk).to eq create_response.allocation_size
65
+ end
66
+
67
+ describe '#set_header_fields' do
68
+ let(:request) { RubySMB::SMB2::Packet::ReadRequest.new }
69
+ it 'calls the set_header_field method from the Tree' do
70
+ expect(tree).to receive(:set_header_fields).with(request).and_call_original
71
+ file.set_header_fields(request)
72
+ end
73
+
74
+ it 'sets the packet file_id from the guid' do
75
+ expect(file.set_header_fields(request).file_id).to eq file.guid
76
+ end
77
+ end
78
+
79
+ describe '#read_packet' do
80
+ it 'creates a new ReadRequest packet' do
81
+ expect(RubySMB::SMB2::Packet::ReadRequest).to receive(:new).and_call_original
82
+ file.read_packet
83
+ end
84
+
85
+ it 'calls #set_header_fields' do
86
+ expect(file).to receive(:set_header_fields).and_call_original
87
+ file.read_packet
88
+ end
89
+
90
+ it 'sets the read_length of the packet' do
91
+ expect(file.read_packet(read_length: 55).read_length).to eq 55
92
+ end
93
+
94
+ it 'sets the offset of the packet' do
95
+ expect(file.read_packet(offset: 55).offset).to eq 55
96
+ end
97
+ end
98
+
99
+ describe '#read' do
100
+ context 'for a small file' do
101
+ let(:small_read) { file.read_packet(read_length: 108) }
102
+ let(:small_response) { RubySMB::SMB2::Packet::ReadResponse.new(data_length: 9, buffer: 'fake data') }
103
+
104
+ it 'uses a single packet to read the entire file' do
105
+ expect(file).to receive(:read_packet).with(read_length: 108, offset: 0).and_return(small_read)
106
+ expect(client).to receive(:send_recv).with(small_read).and_return 'fake data'
107
+ expect(RubySMB::SMB2::Packet::ReadResponse).to receive(:read).with('fake data').and_return(small_response)
108
+ expect(file.read).to eq 'fake data'
109
+ end
110
+ end
111
+
112
+ context 'for a larger file' do
113
+ let(:big_read) { file.read_packet(read_length: 108) }
114
+ let(:big_response) { RubySMB::SMB2::Packet::ReadResponse.new(data_length: 9, buffer: 'fake data') }
115
+
116
+ it 'uses a multiple packet to read the file in chunks' do
117
+ expect(file).to receive(:read_packet).once.with(read_length: described_class::MAX_PACKET_SIZE, offset: 0).and_return(big_read)
118
+ expect(file).to receive(:read_packet).once.with(read_length: described_class::MAX_PACKET_SIZE, offset: described_class::MAX_PACKET_SIZE).and_return(big_read)
119
+ expect(client).to receive(:send_recv).twice.and_return 'fake data'
120
+ expect(RubySMB::SMB2::Packet::ReadResponse).to receive(:read).twice.with('fake data').and_return(big_response)
121
+ file.read(bytes: (described_class::MAX_PACKET_SIZE * 2))
122
+ end
123
+ end
124
+ end
125
+
126
+ describe '#append' do
127
+ it 'call #write with offset set to the end of the file' do
128
+ expect(file).to receive(:write).with(data:'test', offset: file.size)
129
+ file.append(data:'test')
130
+ end
131
+ end
132
+
133
+ describe '#write_packet' do
134
+ it 'calls #set_header_fields with the newly created packet' do
135
+ expect(file).to receive(:set_header_fields).and_call_original
136
+ file.write_packet
137
+ end
138
+
139
+ it 'sets the offset on the packet' do
140
+ expect(file.write_packet(offset:5).write_offset).to eq 5
141
+ end
142
+
143
+ it 'sets the buffer on the packet' do
144
+ expect(file.write_packet(data:'hello').buffer).to eq 'hello'
145
+ end
146
+ end
147
+
148
+ describe '#write' do
149
+ let(:write_response) { RubySMB::SMB2::Packet::WriteResponse.new }
150
+ context 'for a small write' do
151
+ it 'sends a single packet' do
152
+ expect(client).to receive(:send_recv).once.and_return(write_response.to_binary_s)
153
+ file.write(data: 'test')
154
+ end
155
+ end
156
+
157
+ context 'for a large write' do
158
+ it 'sends multiple packets' do
159
+ expect(client).to receive(:send_recv).twice.and_return(write_response.to_binary_s)
160
+ file.write(data: SecureRandom.random_bytes(described_class::MAX_PACKET_SIZE + 1))
161
+ end
162
+ end
163
+ end
164
+
165
+ describe '#delete_packet' do
166
+ it 'creates a new SetInfoRequest packet' do
167
+ expect(RubySMB::SMB2::Packet::SetInfoRequest).to receive(:new).and_call_original
168
+ file.delete_packet
169
+ end
170
+
171
+ it 'calls #set_header_fields' do
172
+ expect(file).to receive(:set_header_fields).and_call_original
173
+ file.delete_packet
174
+ end
175
+
176
+ it 'sets the file_info_class of the packet' do
177
+ expect(file.delete_packet.file_info_class).to eq RubySMB::Fscc::FileInformation::FILE_DISPOSITION_INFORMATION
178
+ end
179
+
180
+ it 'sets the delete_pending field to 1' do
181
+ expect(file.delete_packet.buffer.delete_pending).to eq 1
182
+ end
183
+ end
184
+
185
+ describe '#delete' do
186
+ context 'for a small file' do
187
+ let(:small_delete) { file.delete_packet }
188
+ let(:small_response) { RubySMB::SMB2::Packet::SetInfoResponse.new }
189
+
190
+ it 'uses a single packet to delete the entire file' do
191
+ expect(file).to receive(:delete_packet).and_return(small_delete)
192
+ expect(client).to receive(:send_recv).with(small_delete).and_return 'raw_response'
193
+ expect(RubySMB::SMB2::Packet::SetInfoResponse).to receive(:read).with('raw_response').and_return(small_response)
194
+ expect(file.delete).to eq WindowsError::NTStatus::STATUS_SUCCESS
195
+ end
196
+ end
197
+ end
198
+
199
+ describe '#rename_packet' do
200
+ it 'creates a new SetInfoRequest packet' do
201
+ expect(RubySMB::SMB2::Packet::SetInfoRequest).to receive(:new).and_call_original
202
+ file.rename_packet('new_file.txt')
203
+ end
204
+
205
+ it 'calls #set_header_fields' do
206
+ expect(file).to receive(:set_header_fields).and_call_original
207
+ file.rename_packet('new_file.txt')
208
+ end
209
+
210
+ it 'sets the file_info_class of the packet' do
211
+ expect(file.rename_packet('new_file.txt').file_info_class).to eq RubySMB::Fscc::FileInformation::FILE_RENAME_INFORMATION
212
+ end
213
+
214
+ it 'sets the file_name field to the unicode-encoded new file name' do
215
+ filename = "new_file.txt"
216
+ expect(file.rename_packet(filename).buffer.file_name).to eq filename.encode('UTF-16LE').force_encoding('ASCII-8BIT')
217
+ end
218
+ end
219
+
220
+ describe '#rename' do
221
+ context 'for a small file' do
222
+ let(:small_rename) { file.rename_packet('new_file.txt') }
223
+ let(:small_response) { RubySMB::SMB2::Packet::SetInfoResponse.new }
224
+
225
+ it 'uses a single packet to rename the entire file' do
226
+ expect(file).to receive(:rename_packet).and_return(small_rename)
227
+ expect(client).to receive(:send_recv).with(small_rename).and_return 'raw_response'
228
+ expect(RubySMB::SMB2::Packet::SetInfoResponse).to receive(:read).with('raw_response').and_return(small_response)
229
+ expect(file.rename('new_file.txt')).to eq WindowsError::NTStatus::STATUS_SUCCESS
230
+ end
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::SMB2::Packet::CloseRequest 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 :flags }
9
+ it { is_expected.to respond_to :file_id }
10
+
11
+ it 'is little endian' do
12
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
13
+ end
14
+
15
+ describe '#smb2_header' do
16
+ subject(:header) { packet.smb2_header }
17
+
18
+ it 'is a standard SMB Header' do
19
+ expect(header).to be_a RubySMB::SMB2::SMB2Header
20
+ end
21
+
22
+ it 'should have the command set to SMB_COM_CLOSE' do
23
+ expect(header.command).to eq RubySMB::SMB2::Commands::CLOSE
24
+ end
25
+
26
+ it 'should not have the response flag set' do
27
+ expect(header.flags.reply).to eq 0
28
+ end
29
+ end
30
+
31
+ it 'should have a structure size of 24' do
32
+ expect(packet.structure_size).to eq 24
33
+ end
34
+
35
+ describe '#file_id' do
36
+ it 'should be an SMB FileID field' do
37
+ expect(packet.file_id).to be_a RubySMB::Field::Smb2Fileid
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::SMB2::Packet::CloseResponse 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 :flags }
9
+ it { is_expected.to respond_to :create_time }
10
+ it { is_expected.to respond_to :last_access }
11
+ it { is_expected.to respond_to :last_write }
12
+ it { is_expected.to respond_to :last_change }
13
+ it { is_expected.to respond_to :allocation_size }
14
+ it { is_expected.to respond_to :end_of_file }
15
+ it { is_expected.to respond_to :file_attributes }
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 SMB Header' do
25
+ expect(header).to be_a RubySMB::SMB2::SMB2Header
26
+ end
27
+
28
+ it 'should have the command set to SMB_COM_CLOSE' do
29
+ expect(header.command).to eq RubySMB::SMB2::Commands::CLOSE
30
+ end
31
+
32
+ it 'should have the response flag set' do
33
+ expect(header.flags.reply).to eq 1
34
+ end
35
+ end
36
+
37
+ it 'should have a structure size of 60' do
38
+ expect(packet.structure_size).to eq 60
39
+ end
40
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::SMB2::Packet::CreateRequest 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::CREATE
22
+ end
23
+
24
+ it 'should not have the response flag set' do
25
+ expect(header.flags.reply).to eq 0
26
+ end
27
+ end
28
+
29
+ it 'should have a structure size of 57' do
30
+ expect(packet.structure_size).to eq 57
31
+ end
32
+
33
+ describe '#desired_access' do
34
+ it 'should be a DirectoryAccessMask when the file is a directory' do
35
+ packet.file_attributes.directory = 1
36
+ access_mask = packet.desired_access.send(:current_choice)
37
+ expect(access_mask.class).to eq RubySMB::SMB2::BitField::DirectoryAccessMask
38
+ end
39
+
40
+ it 'should be a FileAccessMask when the file is not a directory' do
41
+ packet.file_attributes.directory = 0
42
+ access_mask = packet.desired_access.send(:current_choice)
43
+ expect(access_mask.class).to eq RubySMB::SMB2::BitField::FileAccessMask
44
+ end
45
+ end
46
+
47
+ describe '#share_accesss' do
48
+ subject(:flags) { packet.share_access }
49
+
50
+ describe '#read_access' do
51
+ it 'should be a 1-bit field per the SMB spec' do
52
+ expect(flags.read_access).to be_a BinData::Bit1
53
+ end
54
+
55
+ it_behaves_like 'bit field with one flag set', :read_access, 'V', 0x00000001
56
+ end
57
+
58
+ describe '#write_access' do
59
+ it 'should be a 1-bit field per the SMB spec' do
60
+ expect(flags.write_access).to be_a BinData::Bit1
61
+ end
62
+
63
+ it_behaves_like 'bit field with one flag set', :write_access, 'V', 0x00000002
64
+ end
65
+
66
+ describe '#delete_access' do
67
+ it 'should be a 1-bit field per the SMB spec' do
68
+ expect(flags.delete_access).to be_a BinData::Bit1
69
+ end
70
+
71
+ it_behaves_like 'bit field with one flag set', :delete_access, 'V', 0x00000004
72
+ end
73
+ end
74
+
75
+ it 'has a CreateOptions field cleverly labeled create_options' do
76
+ expect(packet.create_options).to be_a RubySMB::SMB1::BitField::CreateOptions
77
+ end
78
+
79
+ it 'tracks the offset to #name in #name_offset' do
80
+ expect(packet.name_offset).to eq packet.name.abs_offset
81
+ end
82
+
83
+ it 'tracks the offset to #context in #context_offset' do
84
+ expect(packet.context_offset).to eq packet.context.abs_offset
85
+ end
86
+
87
+ it 'tracks the length of #name in #name_length' do
88
+ expect(packet.name_length).to eq packet.name.length
89
+ end
90
+
91
+ it 'tracks the length of #context in #context_length' do
92
+ expect(packet.context_length).to eq packet.context.do_num_bytes
93
+ end
94
+
95
+ describe '#name' do
96
+ it 'encodes any input into UTF-16LE' do
97
+ packet.name = 'Hello'
98
+ expect(packet.name.to_binary_s).to eq "H\x00e\x00l\x00l\x00o\x00"
99
+ end
100
+ end
101
+ end