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,29 @@
1
+ module RubySMB
2
+ module SMB2
3
+ # An SMB2_CREATE_CONTEXT struct as defined in
4
+ # [2.2.13.2 SMB2_CREATE_CONTEXT Request Values](https://msdn.microsoft.com/en-us/library/cc246504.aspx)
5
+ class CreateContext < BinData::Record
6
+ endian :little
7
+
8
+ uint32 :next_offset, label: 'Offset to next Context'
9
+ uint16 :name_offset, label: 'Offset to Name/Tag', initial_value: -> { name.rel_offset }
10
+ uint16 :name_length, label: 'Length of Name/Tag', initial_value: -> { name.length }
11
+ uint16 :reserved, label: 'Reserved Space'
12
+ uint16 :data_offset, label: 'Offset to data', initial_value: -> { calc_data_offset }
13
+ uint32 :data_length, label: 'Length of data', initial_value: -> { data.length }
14
+ string :name, label: 'Name'
15
+ uint32 :reserved2, label: 'Reserved Space'
16
+ string :data, label: 'Data'
17
+
18
+ private
19
+
20
+ def calc_data_offset
21
+ if data.empty?
22
+ 0
23
+ else
24
+ data.rel_offset
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,251 @@
1
+ module RubySMB
2
+ module SMB2
3
+ # Represents a file on the Remote server that we can perform
4
+ # various I/O operations on.
5
+ class File
6
+ # The maximum number of byte we want to read or write
7
+ # in a single packet.
8
+ MAX_PACKET_SIZE = 32_768
9
+
10
+ # The {FileAttributes} for the file
11
+ # @!attribute [rw] attributes
12
+ # @return [RubySMB::Fscc::FileAttributes]
13
+ attr_accessor :attributes
14
+
15
+ # The {Smb2FileId} for the file
16
+ # @!attribute [rw] guid
17
+ # @return [RubySMB::Field::Smb2FileId]
18
+ attr_accessor :guid
19
+
20
+ # The last access date/time for the file
21
+ # @!attribute [rw] last_access
22
+ # @return [DateTime]
23
+ attr_accessor :last_access
24
+
25
+ # The last change date/time for the file
26
+ # @!attribute [rw] last_change
27
+ # @return [DateTime]
28
+ attr_accessor :last_change
29
+
30
+ # The last write date/time for the file
31
+ # @!attribute [rw] last_write
32
+ # @return [DateTime]
33
+ attr_accessor :last_write
34
+
35
+ # The name of the file
36
+ # @!attribute [rw] name
37
+ # @return [String]
38
+ attr_accessor :name
39
+
40
+ # The actual size, in bytes, of the file
41
+ # @!attribute [rw] size
42
+ # @return [Integer]
43
+ attr_accessor :size
44
+
45
+ # The size in bytes that the file occupies on disk
46
+ # @!attribute [rw] size_on_disk
47
+ # @return [Integer]
48
+ attr_accessor :size_on_disk
49
+
50
+ # The {RubySMB::SMB2::Tree} that this file belong to
51
+ # @!attribute [rw] tree
52
+ # @return [RubySMB::SMB2::Tree]
53
+ attr_accessor :tree
54
+
55
+ def initialize(tree:, response:, name:)
56
+ raise ArgumentError, 'No Tree Provided' if tree.nil?
57
+ raise ArgumentError, 'No Response Provided' if response.nil?
58
+
59
+ @tree = tree
60
+ @name = name
61
+
62
+ @attributes = response.file_attributes
63
+ @guid = response.file_id
64
+ @last_access = response.last_access.to_datetime
65
+ @last_change = response.last_change.to_datetime
66
+ @last_write = response.last_write.to_datetime
67
+ @size = response.end_of_file
68
+ @size_on_disk = response.allocation_size
69
+ end
70
+
71
+ # Appends the supplied data to the end of the file.
72
+ #
73
+ # @param data [String] the data to write to the file
74
+ # @return [WindowsError::ErrorCode] the NTStatus code returned from the operation
75
+ def append(data:'')
76
+ write(data: data, offset: size)
77
+ end
78
+
79
+ # Closes the handle to the remote file.
80
+ #
81
+ # @return [WindowsError::ErrorCode] the NTStatus code returned by the operation
82
+ def close
83
+ close_request = set_header_fields(RubySMB::SMB2::Packet::CloseRequest.new)
84
+ raw_response = tree.client.send_recv(close_request)
85
+ response = RubySMB::SMB2::Packet::CloseResponse.read(raw_response)
86
+ response.smb2_header.nt_status.to_nt_status
87
+ end
88
+
89
+ # Read from the file, a specific number of bytes
90
+ # from a specific offset. If no parameters are given
91
+ # it will read the entire file.
92
+ #
93
+ # @param bytes [Integer] the number of bytes to read
94
+ # @param offset [Integer] the byte offset in the file to start reading from
95
+ # @return [String] the data read from the file
96
+ def read(bytes: size, offset: 0)
97
+ atomic_read_size = if bytes > MAX_PACKET_SIZE
98
+ MAX_PACKET_SIZE
99
+ else
100
+ bytes
101
+ end
102
+
103
+ read_request = read_packet(read_length: atomic_read_size, offset: offset)
104
+ raw_response = tree.client.send_recv(read_request)
105
+ response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
106
+
107
+ data = response.buffer.to_binary_s
108
+
109
+ remaining_bytes = bytes - atomic_read_size
110
+
111
+ while remaining_bytes > 0
112
+ offset += atomic_read_size
113
+ atomic_read_size = remaining_bytes if remaining_bytes < MAX_PACKET_SIZE
114
+
115
+ read_request = read_packet(read_length: atomic_read_size, offset: offset)
116
+ raw_response = tree.client.send_recv(read_request)
117
+ response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
118
+
119
+ data << response.buffer.to_binary_s
120
+ remaining_bytes -= atomic_read_size
121
+ end
122
+ data
123
+ end
124
+
125
+ # Crafts the ReadRequest packet to be sent for read operations.
126
+ #
127
+ # @param bytes [Integer] the number of bytes to read
128
+ # @param offset [Integer] the byte offset in the file to start reading from
129
+ # @return [RubySMB::SMB2::Packet::ReadRequest] the data read from the file
130
+ def read_packet(read_length: 0, offset: 0)
131
+ read_request = set_header_fields(RubySMB::SMB2::Packet::ReadRequest.new)
132
+ read_request.read_length = read_length
133
+ read_request.offset = offset
134
+ read_request
135
+ end
136
+
137
+ def send_recv_read(read_length: 0, offset: 0)
138
+ read_request = read_packet(read_length: read_length, offset: offset)
139
+ raw_response = tree.client.send_recv(read_request)
140
+ response = RubySMB::SMB2::Packet::ReadResponse.read(raw_response)
141
+ if response.status_code == WindowsError::NTStatus::STATUS_PENDING
142
+ sleep 1
143
+ return send_recv_read(read_length: read_length, offset: offset)
144
+ elsif response.status_code != WindowsError::NTStatus::STATUS_SUCCESS
145
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
146
+ end
147
+ response.buffer.to_binary_s
148
+ end
149
+
150
+ # Delete a file on close
151
+ #
152
+ # @return [WindowsError::ErrorCode] the NTStatus Response code
153
+ def delete
154
+ raw_response = tree.client.send_recv(delete_packet)
155
+ response = RubySMB::SMB2::Packet::SetInfoResponse.read(raw_response)
156
+ response.smb2_header.nt_status.to_nt_status
157
+ end
158
+
159
+ # Crafts the SetInfoRequest packet to be sent for delete operations.
160
+ #
161
+ # @return [RubySMB::SMB2::Packet::SetInfoRequest] the set info packet
162
+ def delete_packet
163
+ delete_request = set_header_fields(RubySMB::SMB2::Packet::SetInfoRequest.new)
164
+ delete_request.file_info_class = RubySMB::Fscc::FileInformation::FILE_DISPOSITION_INFORMATION
165
+ delete_request.buffer.delete_pending = 1
166
+ delete_request
167
+ end
168
+
169
+ # Sets the header fields that we have to set on every packet
170
+ # we send for File operations.
171
+ # @param request [RubySMB::GenericPacket] the request packet to set fields on
172
+ # @return [RubySMB::GenericPacket] the rmodified request packet
173
+ def set_header_fields(request)
174
+ request = tree.set_header_fields(request)
175
+ request.file_id = guid
176
+ request
177
+ end
178
+
179
+ # Write the supplied data to the file at the given offset.
180
+ #
181
+ # @param data [String] the data to write to the file
182
+ # @param offset [Integer] the offset in the file to start writing from
183
+ # @return [WindowsError::ErrorCode] the NTStatus code returned from the operation
184
+ def write(data:'', offset: 0)
185
+ buffer = data.dup
186
+ bytes = data.length
187
+ atomic_write_size = if bytes > MAX_PACKET_SIZE
188
+ MAX_PACKET_SIZE
189
+ else
190
+ bytes
191
+ end
192
+
193
+ while buffer.length > 0 do
194
+ write_request = write_packet(data: buffer.slice!(0,atomic_write_size), offset: offset)
195
+ raw_response = tree.client.send_recv(write_request)
196
+ response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
197
+ status = response.smb2_header.nt_status.to_nt_status
198
+
199
+ offset+= atomic_write_size
200
+ return status unless status == WindowsError::NTStatus::STATUS_SUCCESS
201
+ end
202
+
203
+ status
204
+ end
205
+
206
+ # Creates the Request packet for the #write command
207
+ #
208
+ # @param data [String] the data to write to the file
209
+ # @param offset [Integer] the offset in the file to start writing from
210
+ # @return []RubySMB::SMB2::Packet::WriteRequest] the request packet
211
+ def write_packet(data:'', offset: 0)
212
+ write_request = set_header_fields(RubySMB::SMB2::Packet::WriteRequest.new)
213
+ write_request.write_offset = offset
214
+ write_request.buffer = data
215
+ write_request
216
+ end
217
+
218
+ def send_recv_write(data:'', offset: 0)
219
+ pkt = write_packet(data: data, offset: offset)
220
+ raw_response = tree.client.send_recv(pkt)
221
+ response = RubySMB::SMB2::Packet::WriteResponse.read(raw_response)
222
+ if response.status_code != WindowsError::NTStatus::STATUS_SUCCESS
223
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
224
+ end
225
+ response.write_count
226
+ end
227
+
228
+ # Rename a file
229
+ #
230
+ # @param new_file_name [String] the new name
231
+ # @return [WindowsError::ErrorCode] the NTStatus Response code
232
+ def rename(new_file_name)
233
+ raw_response = tree.client.send_recv(rename_packet(new_file_name))
234
+ response = RubySMB::SMB2::Packet::SetInfoResponse.read(raw_response)
235
+ response.smb2_header.nt_status.to_nt_status
236
+ end
237
+
238
+ # Crafts the SetInfoRequest packet to be sent for rename operations.
239
+ #
240
+ # @param new_file_name [String] the new name
241
+ # @return [RubySMB::SMB2::Packet::SetInfoRequest] the set info packet
242
+ def rename_packet(new_file_name)
243
+ rename_request = set_header_fields(RubySMB::SMB2::Packet::SetInfoRequest.new)
244
+ rename_request.file_info_class = RubySMB::Fscc::FileInformation::FILE_RENAME_INFORMATION
245
+ rename_request.buffer.file_name = new_file_name.encode('utf-16le')
246
+ rename_request
247
+ end
248
+
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,21 @@
1
+ module RubySMB
2
+ module SMB2
3
+ # Contains constants for the InfoType values as defined in
4
+ # [2.2.39 SMB2 SET_INFO Request](https://msdn.microsoft.com/en-us/library/cc246560.aspx) and
5
+ # [2.2.37 SMB2 QUERY_INFO Request](https://msdn.microsoft.com/en-us/library/cc246557.aspx)
6
+ module InfoType
7
+ # The file information
8
+ SMB2_0_INFO_FILE = 0x01
9
+
10
+ # The underlying object store information
11
+ SMB2_0_INFO_FILESYSTEM = 0x02
12
+
13
+ # The security information
14
+ SMB2_0_INFO_SECURITY = 0x03
15
+
16
+ # The underlying object store quota information
17
+ SMB2_0_INFO_QUOTA = 0x04
18
+ end
19
+ end
20
+ end
21
+
@@ -1,5 +1,7 @@
1
1
  module RubySMB
2
2
  module SMB2
3
+ # Namespace for all of the packet definitions for SMB2
4
+ # see [2.2 Message Syntax](https://msdn.microsoft.com/en-us/library/cc246497.aspx)
3
5
  module Packet
4
6
  require 'ruby_smb/smb2/packet/error_packet'
5
7
  require 'ruby_smb/smb2/packet/negotiate_request'
@@ -14,6 +16,20 @@ module RubySMB
14
16
  require 'ruby_smb/smb2/packet/logoff_response'
15
17
  require 'ruby_smb/smb2/packet/echo_request'
16
18
  require 'ruby_smb/smb2/packet/echo_response'
19
+ require 'ruby_smb/smb2/packet/create_request'
20
+ require 'ruby_smb/smb2/packet/create_response'
21
+ require 'ruby_smb/smb2/packet/query_directory_request'
22
+ require 'ruby_smb/smb2/packet/query_directory_response'
23
+ require 'ruby_smb/smb2/packet/read_request'
24
+ require 'ruby_smb/smb2/packet/read_response'
25
+ require 'ruby_smb/smb2/packet/set_info_request'
26
+ require 'ruby_smb/smb2/packet/set_info_response'
27
+ require 'ruby_smb/smb2/packet/close_request'
28
+ require 'ruby_smb/smb2/packet/close_response'
29
+ require 'ruby_smb/smb2/packet/write_request'
30
+ require 'ruby_smb/smb2/packet/write_response'
31
+ require 'ruby_smb/smb2/packet/ioctl_request'
32
+ require 'ruby_smb/smb2/packet/ioctl_response'
17
33
  end
18
34
  end
19
35
  end
@@ -0,0 +1,22 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Packet
4
+ # An SMB2 Close Request Packet as defined in
5
+ # [2.2.15 SMB2 CLOSE Request](https://msdn.microsoft.com/en-us/library/cc246523.aspx)
6
+ class CloseRequest < RubySMB::GenericPacket
7
+ endian :little
8
+
9
+ smb2_header :smb2_header
10
+ uint16 :structure_size, label: 'Structure Size', initial_value: 24
11
+ uint16 :flags, label: 'Flags'
12
+ uint32 :reserved, label: 'Reserved Space'
13
+ smb2_fileid :file_id, label: 'File ID'
14
+
15
+ def initialize_instance
16
+ super
17
+ smb2_header.command = RubySMB::SMB2::Commands::CLOSE
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Packet
4
+ # An SMB2 Close Response Packet as defined in
5
+ # [2.2.16 SMB2 CLOSE Response](https://msdn.microsoft.com/en-us/library/cc246524.aspx)
6
+ class CloseResponse < RubySMB::GenericPacket
7
+ endian :little
8
+
9
+ smb2_header :smb2_header
10
+ uint16 :structure_size, label: 'Structure Size', initial_value: 60
11
+ uint16 :flags, label: 'Flags'
12
+ uint32 :reserved, label: 'Reserved Space'
13
+ file_time :create_time, label: 'Create Time'
14
+ file_time :last_access, label: 'Last Accessed Time'
15
+ file_time :last_write, label: 'Last Write Time'
16
+ file_time :last_change, label: 'Last Modified Time'
17
+ uint64 :allocation_size, label: 'Allocated Size'
18
+ uint64 :end_of_file, label: 'End of File'
19
+ file_attributes :file_attributes, label: 'File Attributes'
20
+
21
+ def initialize_instance
22
+ super
23
+ smb2_header.command = RubySMB::SMB2::Commands::CLOSE
24
+ smb2_header.flags.reply = 1
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,54 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Packet
4
+ # An SMB2 Create Request Packet as defined in
5
+ # [2.2.13 SMB2 CREATE Request](https://msdn.microsoft.com/en-us/library/cc246502.aspx)
6
+ class CreateRequest < RubySMB::GenericPacket
7
+ require 'ruby_smb/smb1/bit_field/create_options'
8
+
9
+ endian :little
10
+ smb2_header :smb2_header
11
+ uint16 :structure_size, label: 'Structure Size', initial_value: 57
12
+ uint8 :security_flag, label: 'Security Flags(Do not Use)', initial_value: 0
13
+ uint8 :requested_oplock, label: 'Requested OpLock Level', initial_value: 0
14
+ uint32 :impersonation_level, label: 'Impersonation Level'
15
+ uint64 :create_flags, label: 'Create Flags(Do not use)', initial_value: 0
16
+ uint64 :reserved, label: 'Reserved', initial_value: 0
17
+
18
+ choice :desired_access, selection: -> { file_attributes.directory } do
19
+ file_access_mask 0, label: 'Desired Access'
20
+ directory_access_mask 1, label: 'Desired Access'
21
+ end
22
+
23
+ file_attributes :file_attributes, label: 'File Attributes'
24
+
25
+ struct :share_access do
26
+ bit5 :reserved, label: 'Reserved Space'
27
+ bit1 :delete_access, label: 'Share Delete Access'
28
+ bit1 :write_access, label: 'Share Write Access'
29
+ bit1 :read_access, label: 'Share Read Access'
30
+ # byte boundary
31
+ bit8 :reserved2, label: 'Reserved Space'
32
+ bit8 :reserved3, label: 'Reserved Space'
33
+ bit8 :reserved4, label: 'Reserved Space'
34
+ end
35
+
36
+ uint32 :create_disposition, label: 'Create Disposition'
37
+ create_options :create_options
38
+ uint16 :name_offset, label: 'Name Offset', initial_value: -> { name.abs_offset }
39
+ uint16 :name_length, label: 'Name Length', initial_value: -> { name.do_num_bytes }
40
+ uint32 :context_offset, label: 'Create Context Offset', initial_value: -> { context.abs_offset }
41
+ uint32 :context_length, label: 'Create Context Length', initial_value: -> { context.do_num_bytes }
42
+ string16 :name, label: 'File Name'
43
+ uint32 :reserved5, label: 'Reserved Space'
44
+
45
+ array :context, label: 'Contexts', type: :create_context, read_until: :eof
46
+
47
+ def initialize_instance
48
+ super
49
+ smb2_header.command = RubySMB::SMB2::Commands::CREATE
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Packet
4
+ # An SMB2 Create Response Packet as defined in
5
+ # [2.2.14 SMB2 CREATE Response](https://msdn.microsoft.com/en-us/library/cc246512.aspx)
6
+ class CreateResponse < RubySMB::GenericPacket
7
+ endian :little
8
+ smb2_header :smb2_header
9
+ uint16 :structure_size, label: 'Structure Size', initial_value: 89
10
+ uint8 :oplock_level, label: 'Granted OpLock Level'
11
+ uint8 :flags, label: 'Flags (Do Not Use)'
12
+ uint32 :create_action, label: 'Create Action'
13
+ file_time :create_time, label: 'Create Time'
14
+ file_time :last_access, label: 'Last Accessed Time'
15
+ file_time :last_write, label: 'Last Write Time'
16
+ file_time :last_change, label: 'Last Modified Time'
17
+ uint64 :allocation_size, label: 'Allocated Size'
18
+ uint64 :end_of_file, label: 'Size in Bytes'
19
+ file_attributes :file_attributes, label: 'File Attributes'
20
+ uint32 :reserved, label: 'Reserved Space'
21
+ smb2_fileid :file_id, label: 'File ID'
22
+ uint32 :context_offset, label: 'Create Context Offset', initial_value: -> { context.abs_offset }
23
+ uint32 :context_length, label: 'Create Context Length', initial_value: -> { context.do_num_bytes }
24
+
25
+ array :context, label: 'Contexts', type: :create_context, read_until: :eof
26
+
27
+ def initialize_instance
28
+ super
29
+ smb2_header.command = RubySMB::SMB2::Commands::CREATE
30
+ smb2_header.flags.reply = 1
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end